freeablo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
nuklear.h
Go to the documentation of this file.
1 /*
2  Nuklear - 1.37.0 - public domain
3  no warrenty implied; use at your own risk.
4  authored from 2015-2017 by Micha Mettke
5 
6 ABOUT:
7  This is a minimal state graphical user interface single header toolkit
8  written in ANSI C and licensed under public domain.
9  It was designed as a simple embeddable user interface for application and does
10  not have any dependencies, a default renderbackend or OS window and input handling
11  but instead provides a very modular library approach by using simple input state
12  for input and draw commands describing primitive shapes as output.
13  So instead of providing a layered library that tries to abstract over a number
14  of platform and render backends it only focuses on the actual UI.
15 
16 VALUES:
17  - Graphical user interface toolkit
18  - Single header library
19  - Written in C89 (a.k.a. ANSI C or ISO C90)
20  - Small codebase (~17kLOC)
21  - Focus on portability, efficiency and simplicity
22  - No dependencies (not even the standard library if not wanted)
23  - Fully skinnable and customizable
24  - Low memory footprint with total memory control if needed or wanted
25  - UTF-8 support
26  - No global or hidden state
27  - Customizable library modules (you can compile and use only what you need)
28  - Optional font baker and vertex buffer output
29 
30 USAGE:
31  This library is self contained in one single header file and can be used either
32  in header only mode or in implementation mode. The header only mode is used
33  by default when included and allows including this header in other headers
34  and does not contain the actual implementation.
35 
36  The implementation mode requires to define the preprocessor macro
37  NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.:
38 
39  #define NK_IMPLEMENTATION
40  #include "nuklear.h"
41 
42  Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
43  below in header and implementation mode if you want to use additional functionality
44  or need more control over the library.
45  IMPORTANT: Every time you include "nuklear.h" you have to define the same flags.
46  This is very important not doing it either leads to compiler errors
47  or even worse stack corruptions.
48 
49 FEATURES:
50  - Absolutely no platform dependend code
51  - Memory management control ranging from/to
52  - Ease of use by allocating everything from standard library
53  - Control every byte of memory inside the library
54  - Font handling control ranging from/to
55  - Use your own font implementation for everything
56  - Use this libraries internal font baking and handling API
57  - Drawing output control ranging from/to
58  - Simple shapes for more high level APIs which already have drawing capabilities
59  - Hardware accessible anti-aliased vertex buffer output
60  - Customizable colors and properties ranging from/to
61  - Simple changes to color by filling a simple color table
62  - Complete control with ability to use skinning to decorate widgets
63  - Bendable UI library with widget ranging from/to
64  - Basic widgets like buttons, checkboxes, slider, ...
65  - Advanced widget like abstract comboboxes, contextual menus,...
66  - Compile time configuration to only compile what you need
67  - Subset which can be used if you do not want to link or use the standard library
68  - Can be easily modified to only update on user input instead of frame updates
69 
70 OPTIONAL DEFINES:
71  NK_PRIVATE
72  If defined declares all functions as static, so they can only be accessed
73  inside the file that contains the implementation
74 
75  NK_INCLUDE_FIXED_TYPES
76  If defined it will include header <stdint.h> for fixed sized types
77  otherwise nuklear tries to select the correct type. If that fails it will
78  throw a compiler error and you have to select the correct types yourself.
79  <!> If used needs to be defined for implementation and header <!>
80 
81  NK_INCLUDE_DEFAULT_ALLOCATOR
82  if defined it will include header <stdlib.h> and provide additional functions
83  to use this library without caring for memory allocation control and therefore
84  ease memory management.
85  <!> Adds the standard library with malloc and free so don't define if you
86  don't want to link to the standard library <!>
87  <!> If used needs to be defined for implementation and header <!>
88 
89  NK_INCLUDE_STANDARD_IO
90  if defined it will include header <stdio.h> and provide
91  additional functions depending on file loading.
92  <!> Adds the standard library with fopen, fclose,... so don't define this
93  if you don't want to link to the standard library <!>
94  <!> If used needs to be defined for implementation and header <!>
95 
96  NK_INCLUDE_STANDARD_VARARGS
97  if defined it will include header <stdarg.h> and provide
98  additional functions depending on variable arguments
99  <!> Adds the standard library with va_list and so don't define this if
100  you don't want to link to the standard library<!>
101  <!> If used needs to be defined for implementation and header <!>
102 
103  NK_INCLUDE_VERTEX_BUFFER_OUTPUT
104  Defining this adds a vertex draw command list backend to this
105  library, which allows you to convert queue commands into vertex draw commands.
106  This is mainly if you need a hardware accessible format for OpenGL, DirectX,
107  Vulkan, Metal,...
108  <!> If used needs to be defined for implementation and header <!>
109 
110  NK_INCLUDE_FONT_BAKING
111  Defining this adds the `stb_truetype` and `stb_rect_pack` implementation
112  to this library and provides font baking and rendering.
113  If you already have font handling or do not want to use this font handler
114  you don't have to define it.
115  <!> If used needs to be defined for implementation and header <!>
116 
117  NK_INCLUDE_DEFAULT_FONT
118  Defining this adds the default font: ProggyClean.ttf into this library
119  which can be loaded into a font atlas and allows using this library without
120  having a truetype font
121  <!> Enabling this adds ~12kb to global stack memory <!>
122  <!> If used needs to be defined for implementation and header <!>
123 
124  NK_INCLUDE_COMMAND_USERDATA
125  Defining this adds a userdata pointer into each command. Can be useful for
126  example if you want to provide custom shaders depending on the used widget.
127  Can be combined with the style structures.
128  <!> If used needs to be defined for implementation and header <!>
129 
130  NK_BUTTON_TRIGGER_ON_RELEASE
131  Different platforms require button clicks occuring either on buttons being
132  pressed (up to down) or released (down to up).
133  By default this library will react on buttons being pressed, but if you
134  define this it will only trigger if a button is released.
135  <!> If used it is only required to be defined for the implementation part <!>
136 
137  NK_ZERO_COMMAND_MEMORY
138  Defining this will zero out memory for each drawing command added to a
139  drawing queue (inside nk_command_buffer_push). Zeroing command memory
140  is very useful for fast checking (using memcmp) if command buffers are
141  equal and avoid drawing frames when nothing on screen has changed since
142  previous frame.
143 
144  NK_ASSERT
145  If you don't define this, nuklear will use <assert.h> with assert().
146  <!> Adds the standard library so define to nothing of not wanted <!>
147  <!> If used needs to be defined for implementation and header <!>
148 
149  NK_BUFFER_DEFAULT_INITIAL_SIZE
150  Initial buffer size allocated by all buffers while using the default allocator
151  functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't
152  want to allocate the default 4k memory then redefine it.
153  <!> If used needs to be defined for implementation and header <!>
154 
155  NK_MAX_NUMBER_BUFFER
156  Maximum buffer size for the conversion buffer between float and string
157  Under normal circumstances this should be more than sufficient.
158  <!> If used needs to be defined for implementation and header <!>
159 
160  NK_INPUT_MAX
161  Defines the max number of bytes which can be added as text input in one frame.
162  Under normal circumstances this should be more than sufficient.
163  <!> If used it is only required to be defined for the implementation part <!>
164 
165  NK_MEMSET
166  You can define this to 'memset' or your own memset implementation
167  replacement. If not nuklear will use its own version.
168  <!> If used it is only required to be defined for the implementation part <!>
169 
170  NK_MEMCPY
171  You can define this to 'memcpy' or your own memcpy implementation
172  replacement. If not nuklear will use its own version.
173  <!> If used it is only required to be defined for the implementation part <!>
174 
175  NK_SQRT
176  You can define this to 'sqrt' or your own sqrt implementation
177  replacement. If not nuklear will use its own slow and not highly
178  accurate version.
179  <!> If used it is only required to be defined for the implementation part <!>
180 
181  NK_SIN
182  You can define this to 'sinf' or your own sine implementation
183  replacement. If not nuklear will use its own approximation implementation.
184  <!> If used it is only required to be defined for the implementation part <!>
185 
186  NK_COS
187  You can define this to 'cosf' or your own cosine implementation
188  replacement. If not nuklear will use its own approximation implementation.
189  <!> If used it is only required to be defined for the implementation part <!>
190 
191  NK_STRTOD
192  You can define this to `strtod` or your own string to double conversion
193  implementation replacement. If not defined nuklear will use its own
194  imprecise and possibly unsafe version (does not handle nan or infinity!).
195  <!> If used it is only required to be defined for the implementation part <!>
196 
197  NK_DTOA
198  You can define this to `dtoa` or your own double to string conversion
199  implementation replacement. If not defined nuklear will use its own
200  imprecise and possibly unsafe version (does not handle nan or infinity!).
201  <!> If used it is only required to be defined for the implementation part <!>
202 
203  NK_VSNPRINTF
204  If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO`
205  and want to be safe define this to `vsnprintf` on compilers supporting
206  later versions of C or C++. By default nuklear will check for your stdlib version
207  in C as well as compiler version in C++. if `vsnprintf` is available
208  it will define it to `vsnprintf` directly. If not defined and if you have
209  older versions of C or C++ it will be defined to `vsprintf` which is unsafe.
210  <!> If used it is only required to be defined for the implementation part <!>
211 
212  NK_BYTE
213  NK_INT16
214  NK_UINT16
215  NK_INT32
216  NK_UINT32
217  NK_SIZE_TYPE
218  NK_POINTER_TYPE
219  If you compile without NK_USE_FIXED_TYPE then a number of standard types
220  will be selected and compile time validated. If they are incorrect you can
221  define the correct types by overloading these type defines.
222 
223 CREDITS:
224  Developed by Micha Mettke and every direct or indirect contributor.
225 
226  Embeds stb_texedit, stb_truetype and stb_rectpack by Sean Barret (public domain)
227  Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license).
228 
229  Big thank you to Omar Cornut (ocornut@github) for his imgui library and
230  giving me the inspiration for this library, Casey Muratori for handmade hero
231  and his original immediate mode graphical user interface idea and Sean
232  Barret for his amazing single header libraries which restored my faith
233  in libraries and brought me to create some of my own.
234 
235 LICENSE:
236  This software is dual-licensed to the public domain and under the following
237  license: you are granted a perpetual, irrevocable license to copy, modify,
238  publish and distribute this file as you see fit.
239 */
240 #ifndef NK_NUKLEAR_H_
241 #define NK_NUKLEAR_H_
242 
243 #ifdef __cplusplus
244 extern "C" {
245 #endif
246 /*
247  * ==============================================================
248  *
249  * CONSTANTS
250  *
251  * ===============================================================
252  */
253 #define NK_UNDEFINED (-1.0f)
254 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
255 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
256 #ifndef NK_INPUT_MAX
257 #define NK_INPUT_MAX 16
258 #endif
259 #ifndef NK_MAX_NUMBER_BUFFER
260 #define NK_MAX_NUMBER_BUFFER 64
261 #endif
262 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
263 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
264 #endif
265 /*
266  * ==============================================================
267  *
268  * HELPER
269  *
270  * ===============================================================
271  */
272 #ifndef NK_API
273  #ifdef NK_PRIVATE
274  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
275  #define NK_API static inline
276  #elif defined(__cplusplus)
277  #define NK_API static inline
278  #else
279  #define NK_API static
280  #endif
281  #else
282  #define NK_API extern
283  #endif
284 #endif
285 
286 #define NK_INTERN static
287 #define NK_STORAGE static
288 #define NK_GLOBAL static
289 
290 #define NK_FLAG(x) (1 << (x))
291 #define NK_STRINGIFY(x) #x
292 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
293 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
294 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
295 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
296 
297 #ifdef _MSC_VER
298 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
299 #else
300 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
301 #endif
302 
303 #ifndef NK_STATIC_ASSERT
304 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
305 #endif
306 
307 #ifndef NK_FILE_LINE
308 #ifdef _MSC_VER
309 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
310 #else
311 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
312 #endif
313 #endif
314 
315 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
316 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
317 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
318 /*
319  * ===============================================================
320  *
321  * BASIC
322  *
323  * ===============================================================
324  */
325 #ifdef NK_INCLUDE_FIXED_TYPES
326  #include <stdint.h>
327  #define NK_INT8 int8_t
328  #define NK_UINT8 uint8_t
329  #define NK_INT16 int16_t
330  #define NK_UINT16 uint16_t
331  #define NK_INT32 int32_t
332  #define NK_UINT32 uint32_t
333  #define NK_SIZE_TYPE uintptr_t
334  #define NK_POINTER_TYPE uintptr_t
335 #else
336  #ifndef NK_INT8
337  #define NK_INT8 char
338  #endif
339  #ifndef NK_UINT8
340  #define NK_UINT8 unsigned char
341  #endif
342  #ifndef NK_INT16
343  #define NK_INT16 signed short
344  #endif
345  #ifndef NK_UINT16
346  #define NK_UINT16 unsigned short
347  #endif
348  #ifndef NK_INT32
349  #if defined(_MSC_VER)
350  #define NK_INT32 __int32
351  #else
352  #define NK_INT32 signed int
353  #endif
354  #endif
355  #ifndef NK_UINT32
356  #if defined(_MSC_VER)
357  #define NK_UINT32 unsigned __int32
358  #else
359  #define NK_UINT32 unsigned int
360  #endif
361  #endif
362  #ifndef NK_SIZE_TYPE
363  #if defined(_WIN64) && defined(_MSC_VER)
364  #define NK_SIZE_TYPE unsigned __int64
365  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
366  #define NK_SIZE_TYPE unsigned __int32
367  #elif defined(__GNUC__) || defined(__clang__)
368  #if defined(__x86_64__) || defined(__ppc64__)
369  #define NK_SIZE_TYPE unsigned long
370  #else
371  #define NK_SIZE_TYPE unsigned int
372  #endif
373  #else
374  #define NK_SIZE_TYPE unsigned long
375  #endif
376  #endif
377  #ifndef NK_POINTER_TYPE
378  #if defined(_WIN64) && defined(_MSC_VER)
379  #define NK_POINTER_TYPE unsigned __int64
380  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
381  #define NK_POINTER_TYPE unsigned __int32
382  #elif defined(__GNUC__) || defined(__clang__)
383  #if defined(__x86_64__) || defined(__ppc64__)
384  #define NK_POINTER_TYPE unsigned long
385  #else
386  #define NK_POINTER_TYPE unsigned int
387  #endif
388  #else
389  #define NK_POINTER_TYPE unsigned long
390  #endif
391  #endif
392 #endif
393 
394 typedef NK_INT8 nk_char;
399 typedef NK_INT32 nk_int;
403 
404 typedef nk_uint nk_hash;
405 typedef nk_uint nk_flags;
406 typedef nk_uint nk_rune;
407 
408 /* Make sure correct type size:
409  * This will fire with a negative subscript error if the type sizes
410  * are set incorrectly by the compiler, and compile out if not */
411 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
412 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
413 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
414 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
415 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
416 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
417 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
418 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
419 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
420 
421 /* ============================================================================
422  *
423  * API
424  *
425  * =========================================================================== */
426 struct nk_buffer;
427 struct nk_allocator;
428 struct nk_command_buffer;
429 struct nk_draw_command;
430 struct nk_convert_config;
431 struct nk_style_item;
432 struct nk_text_edit;
433 struct nk_draw_list;
434 struct nk_user_font;
435 struct nk_panel;
436 struct nk_context;
437 struct nk_draw_vertex_layout_element;
438 struct nk_style_button;
439 struct nk_style_toggle;
440 struct nk_style_selectable;
441 struct nk_style_slide;
442 struct nk_style_progress;
443 struct nk_style_scrollbar;
444 struct nk_style_edit;
445 struct nk_style_property;
446 struct nk_style_chart;
447 struct nk_style_combo;
448 struct nk_style_tab;
450 struct nk_style_window;
451 
453 struct nk_color {nk_byte r,g,b,a;};
454 struct nk_colorf {float r,g,b,a;};
455 struct nk_vec2 {float x,y;};
456 struct nk_vec2i {short x, y;};
457 struct nk_rect {float x,y,w,h;};
458 struct nk_recti {short x,y,w,h;};
459 typedef char nk_glyph[NK_UTF_SIZE];
460 typedef union {void *ptr; int id;} nk_handle;
461 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
462 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
463 struct nk_scroll {nk_uint x, y;};
464 
477 
478 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
479 typedef void (*nk_plugin_free)(nk_handle, void *old);
480 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
481 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
482 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
483 
484 struct nk_allocator {
485  nk_handle userdata;
488 };
504 };
505 /* =============================================================================
506  *
507  * CONTEXT
508  *
509  * =============================================================================*/
510 /* Contexts are the main entry point and the majestro of nuklear and contain all required state.
511  * They are used for window, memory, input, style, stack, commands and time management and need
512  * to be passed into all nuklear GUI specific functions.
513  *
514  * Usage
515  * -------------------
516  * To use a context it first has to be initialized which can be achieved by calling
517  * one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
518  * Each takes in a font handle and a specific way of handling memory. Memory control
519  * hereby ranges from standard library to just specifing a fixed sized block of memory
520  * which nuklear has to manage itself from.
521  *
522  * struct nk_context ctx;
523  * nk_init_xxx(&ctx, ...);
524  * while (1) {
525  * [...]
526  * nk_clear(&ctx);
527  * }
528  * nk_free(&ctx);
529  *
530  * Reference
531  * -------------------
532  * nk_init_default - Initializes context with standard library memory alloction (malloc,free)
533  * nk_init_fixed - Initializes context from single fixed size memory block
534  * nk_init - Initializes context with memory allocator callbacks for alloc and free
535  * nk_init_custom - Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
536  * nk_clear - Called at the end of the frame to reset and prepare the context for the next frame
537  * nk_free - Shutdown and free all memory allocated inside the context
538  * nk_set_user_data - Utility function to pass user data to draw command
539  */
540 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
541 /* nk_init_default - Initializes a `nk_context` struct with a default standard library allocator.
542  * Should be used if you don't want to be bothered with memory management in nuklear.
543  * Parameters:
544  * @ctx must point to an either stack or heap allocated `nk_context` struct
545  * @font must point to a previously initialized font handle for more info look at font documentation
546  * Return values:
547  * true(1) on success
548  * false(0) on failure */
549 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
550 #endif
551 /* nk_init_fixed - Initializes a `nk_context` struct from a single fixed size memory block
552  * Should be used if you want complete control over nuklears memory management.
553  * Especially recommended for system with little memory or systems with virtual memory.
554  * For the later case you can just allocate for example 16MB of virtual memory
555  * and only the required amount of memory will actually be commited.
556  * IMPORTANT: make sure the passed memory block is aligned correctly for `nk_draw_commands`
557  * Parameters:
558  * @ctx must point to an either stack or heap allocated `nk_context` struct
559  * @memory must point to a previously allocated memory block
560  * @size must contain the total size of @memory
561  * @font must point to a previously initialized font handle for more info look at font documentation
562  * Return values:
563  * true(1) on success
564  * false(0) on failure */
565 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
566 /* nk_init - Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
567  * memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
568  * interface to nuklear. Can be useful for cases like monitoring memory consumption.
569  * Parameters:
570  * @ctx must point to an either stack or heap allocated `nk_context` struct
571  * @alloc must point to a previously allocated memory allocator
572  * @font must point to a previously initialized font handle for more info look at font documentation
573  * Return values:
574  * true(1) on success
575  * false(0) on failure */
576 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
577 /* nk_init_custom - Initializes a `nk_context` struct from two different either fixed or growing
578  * buffers. The first buffer is for allocating draw commands while the second buffer is
579  * used for allocating windows, panels and state tables.
580  * Parameters:
581  * @ctx must point to an either stack or heap allocated `nk_context` struct
582  * @cmds must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
583  * @pool must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
584  * @font must point to a previously initialized font handle for more info look at font documentation
585  * Return values:
586  * true(1) on success
587  * false(0) on failure */
588 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
589 /* nk_clear - Resets the context state at the end of the frame. This includes mostly
590  * garbage collector tasks like removing windows or table not called and therefore
591  * used anymore.
592  * Parameters:
593  * @ctx must point to a previously initialized `nk_context` struct */
594 NK_API void nk_clear(struct nk_context*);
595 /* nk_free - Frees all memory allocated by nuklear. Not needed if context was
596  * initialized with `nk_init_fixed`.
597  * Parameters:
598  * @ctx must point to a previously initialized `nk_context` struct */
599 NK_API void nk_free(struct nk_context*);
600 #ifdef NK_INCLUDE_COMMAND_USERDATA
601 /* nk_set_user_data - Sets the currently passed userdata passed down into each draw command.
602  * Parameters:
603  * @ctx must point to a previously initialized `nk_context` struct
604  * @data handle with either pointer or index to be passed into every draw commands */
605 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
606 #endif
607 /* =============================================================================
608  *
609  * INPUT
610  *
611  * =============================================================================*/
612 /* The input API is responsible for holding the current input state composed of
613  * mouse, key and text input states.
614  * It is worth noting that no direct os or window handling is done in nuklear.
615  * Instead all input state has to be provided by platform specific code. This in one hand
616  * expects more work from the user and complicates usage but on the other hand
617  * provides simple abstraction over a big number of platforms, libraries and other
618  * already provided functionality.
619  *
620  * Usage
621  * -------------------
622  * Input state needs to be provided to nuklear by first calling `nk_input_begin`
623  * which resets internal state like delta mouse position and button transistions.
624  * After `nk_input_begin` all current input state needs to be provided. This includes
625  * mouse motion, button and key pressed and released, text input and scrolling.
626  * Both event- or state-based input handling are supported by this API
627  * and should work without problems. Finally after all input state has been
628  * mirrored `nk_input_end` needs to be called to finish input process.
629  *
630  * struct nk_context ctx;
631  * nk_init_xxx(&ctx, ...);
632  * while (1) {
633  * Event evt;
634  * nk_input_begin(&ctx);
635  * while (GetEvent(&evt)) {
636  * if (evt.type == MOUSE_MOVE)
637  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
638  * else if (evt.type == ...) {
639  * ...
640  * }
641  * }
642  * nk_input_end(&ctx);
643  * [...]
644  * nk_clear(&ctx);
645  * }
646  * nk_free(&ctx);
647  *
648  * Reference
649  * -------------------
650  * nk_input_begin - Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
651  * nk_input_motion - Mirrors mouse cursor position
652  * nk_input_key - Mirrors key state with either pressed or released
653  * nk_input_button - Mirrors mouse button state with either pressed or released
654  * nk_input_scroll - Mirrors mouse scroll values
655  * nk_input_char - Adds a single ASCII text character into an internal text buffer
656  * nk_input_glyph - Adds a single multi-byte UTF-8 character into an internal text buffer
657  * nk_input_unicode - Adds a single unicode rune into an internal text buffer
658  * nk_input_end - Ends the input mirroring process by calculating state changes. Don't call any `nk_input_xxx` function referenced above after this call
659  */
660 enum nk_keys {
675  /* Shortcuts: text field */
688  /* Shortcuts: scrollbar */
694 };
701 };
702 /* nk_input_begin - Begins the input mirroring process by resetting text, scroll
703  * mouse previous mouse position and movement as well as key state transistions,
704  * Parameters:
705  * @ctx must point to an previously initialized `nk_context` struct */
706 NK_API void nk_input_begin(struct nk_context*);
707 /* nk_input_motion - Mirros current mouse position to nuklear
708  * Parameters:
709  * @ctx must point to an previously initialized `nk_context` struct
710  * @x must constain an integer describing the current mouse cursor x-position
711  * @y must constain an integer describing the current mouse cursor y-position */
712 NK_API void nk_input_motion(struct nk_context*, int x, int y);
713 /* nk_input_key - Mirros state of a specific key to nuklear
714  * Parameters:
715  * @ctx must point to an previously initialized `nk_context` struct
716  * @key must be any value specified in enum `nk_keys` that needs to be mirrored
717  * @down must be 0 for key is up and 1 for key is down */
718 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
719 /* nk_input_button - Mirros the state of a specific mouse button to nuklear
720  * Parameters:
721  * @ctx must point to an previously initialized `nk_context` struct
722  * @nk_buttons must be any value specified in enum `nk_buttons` that needs to be mirrored
723  * @x must constain an integer describing mouse cursor x-position on click up/down
724  * @y must constain an integer describing mouse cursor y-position on click up/down
725  * @down must be 0 for key is up and 1 for key is down */
726 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
727 /* nk_input_char - Copies a single ASCII character into an internal text buffer
728  * This is basically a helper function to quickly push ASCII characters into
729  * nuklear. Note that you can only push up to NK_INPUT_MAX bytes into
730  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
731  * Parameters:
732  * @ctx must point to an previously initialized `nk_context` struct
733  * @c must be a single ASCII character preferable one that can be printed */
734 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
735 /* nk_input_char - Copies a single ASCII character into an internal text buffer
736  * This is basically a helper function to quickly push ASCII characters into
737  * nuklear. Note that you can only push up to NK_INPUT_MAX bytes into
738  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
739  * Parameters:
740  * @ctx must point to an previously initialized `nk_context` struct
741  * @c must be a single ASCII character preferable one that can be printed */
742 NK_API void nk_input_char(struct nk_context*, char);
743 /* nk_input_unicode - Converts a encoded unicode rune into UTF-8 and copies the result
744  * into an internal text buffer.
745  * Note that you can only push up to NK_INPUT_MAX bytes into
746  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
747  * Parameters:
748  * @ctx must point to an previously initialized `nk_context` struct
749  * @glyph UTF-32 uncode codepoint */
750 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
751 /* nk_input_unicode - Converts a unicode rune into UTF-8 and copies the result
752  * into an internal text buffer.
753  * Note that you can only push up to NK_INPUT_MAX bytes into
754  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
755  * Parameters:
756  * @ctx must point to an previously initialized `nk_context` struct
757  * @glyph UTF-32 uncode codepoint */
758 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
759 /* nk_input_end - End the input mirroring process by resetting mouse grabbing
760  * state to ensure the mouse cursor is not grabbed indefinitely.
761  * Parameters:
762  * @ctx must point to an previously initialized `nk_context` struct */
763 NK_API void nk_input_end(struct nk_context*);
764 /* =============================================================================
765  *
766  * DRAWING
767  *
768  * =============================================================================*/
769 /* This library was designed to be render backend agnostic so it does
770  * not draw anything to screen directly. Instead all drawn shapes, widgets
771  * are made of, are buffered into memory and make up a command queue.
772  * Each frame therefore fills the command buffer with draw commands
773  * that then need to be executed by the user and his own render backend.
774  * After that the command buffer needs to be cleared and a new frame can be
775  * started. It is probably important to note that the command buffer is the main
776  * drawing API and the optional vertex buffer API only takes this format and
777  * converts it into a hardware accessible format.
778  *
779  * Usage
780  * -------------------
781  * To draw all draw commands accumulated over a frame you need your own render
782  * backend able to draw a number of 2D primitives. This includes at least
783  * filled and stroked rectangles, circles, text, lines, triangles and scissors.
784  * As soon as this criterion is met you can iterate over each draw command
785  * and execute each draw command in a interpreter like fashion:
786  *
787  * const struct nk_command *cmd = 0;
788  * nk_foreach(cmd, &ctx) {
789  * switch (cmd->type) {
790  * case NK_COMMAND_LINE:
791  * your_draw_line_function(...)
792  * break;
793  * case NK_COMMAND_RECT
794  * your_draw_rect_function(...)
795  * break;
796  * case ...:
797  * [...]
798  * }
799  *
800  * In program flow context draw commands need to be executed after input has been
801  * gathered and the complete UI with windows and their contained widgets have
802  * been executed and before calling `nk_clear` which frees all previously
803  * allocated draw commands.
804  *
805  * struct nk_context ctx;
806  * nk_init_xxx(&ctx, ...);
807  * while (1) {
808  * Event evt;
809  * nk_input_begin(&ctx);
810  * while (GetEvent(&evt)) {
811  * if (evt.type == MOUSE_MOVE)
812  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
813  * else if (evt.type == [...]) {
814  * [...]
815  * }
816  * }
817  * nk_input_end(&ctx);
818  *
819  * [...]
820  *
821  * const struct nk_command *cmd = 0;
822  * nk_foreach(cmd, &ctx) {
823  * switch (cmd->type) {
824  * case NK_COMMAND_LINE:
825  * your_draw_line_function(...)
826  * break;
827  * case NK_COMMAND_RECT
828  * your_draw_rect_function(...)
829  * break;
830  * case ...:
831  * [...]
832  * }
833  * nk_clear(&ctx);
834  * }
835  * nk_free(&ctx);
836  *
837  * You probably noticed that you have to draw all of the UI each frame which is
838  * quite wasteful. While the actual UI updating loop is quite fast rendering
839  * without actually needing it is not. So there are multiple things you could do.
840  *
841  * First is only update on input. This of course is only an option if your
842  * application only depends on the UI and does not require any outside calculations.
843  * If you actually only update on input make sure to update the UI two times each
844  * frame and call `nk_clear` directly after the first pass and only draw in
845  * the second pass.
846  *
847  * struct nk_context ctx;
848  * nk_init_xxx(&ctx, ...);
849  * while (1) {
850  * [...wait for input ]
851  *
852  * [...do two UI passes ...]
853  * do_ui(...)
854  * nk_clear(&ctx);
855  * do_ui(...)
856  *
857  * const struct nk_command *cmd = 0;
858  * nk_foreach(cmd, &ctx) {
859  * switch (cmd->type) {
860  * case NK_COMMAND_LINE:
861  * your_draw_line_function(...)
862  * break;
863  * case NK_COMMAND_RECT
864  * your_draw_rect_function(...)
865  * break;
866  * case ...:
867  * [...]
868  * }
869  * nk_clear(&ctx);
870  * }
871  * nk_free(&ctx);
872  *
873  * The second probably more applicable trick is to only draw if anything changed.
874  * It is not really useful for applications with continous draw loop but
875  * quite useful for desktop applications. To actually get nuklear to only
876  * draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
877  * allocate a memory buffer that will store each unique drawing output.
878  * After each frame you compare the draw command memory inside the library
879  * with your allocated buffer by memcmp. If memcmp detects differences
880  * you have to copy the nuklears command buffer into the allocated buffer
881  * and then draw like usual (this example uses fixed memory but you could
882  * use dynamically allocated memory).
883  *
884  * [... other defines ...]
885  * #define NK_ZERO_COMMAND_MEMORY
886  * #include "nuklear.h"
887  *
888  * struct nk_context ctx;
889  * void *last = calloc(1,64*1024);
890  * void *buf = calloc(1,64*1024);
891  * nk_init_fixed(&ctx, buf, 64*1024);
892  * while (1) {
893  * [...input...]
894  * [...ui...]
895  *
896  * void *cmds = nk_buffer_memory(&ctx.memory);
897  * if (memcmp(cmds, last, ctx.memory.allocated)) {
898  * memcpy(last,cmds,ctx.memory.allocated);
899  * const struct nk_command *cmd = 0;
900  * nk_foreach(cmd, &ctx) {
901  * switch (cmd->type) {
902  * case NK_COMMAND_LINE:
903  * your_draw_line_function(...)
904  * break;
905  * case NK_COMMAND_RECT
906  * your_draw_rect_function(...)
907  * break;
908  * case ...:
909  * [...]
910  * }
911  * }
912  * }
913  * nk_clear(&ctx);
914  * }
915  * nk_free(&ctx);
916  *
917  * Finally while using draw commands makes sense for higher abstracted platforms like
918  * X11 and Win32 or drawing libraries it is often desirable to use graphics
919  * hardware directly. Therefore it is possible to just define
920  * `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
921  * To access the vertex output you first have to convert all draw commands into
922  * vertexes by calling `nk_convert` which takes in your prefered vertex format.
923  * After successfully converting all draw commands just iterate over and execute all
924  * vertex draw commands:
925  *
926  * struct nk_convert_config cfg = {};
927  * static const struct nk_draw_vertex_layout_element vertex_layout[] = {
928  * {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
929  * {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
930  * {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
931  * {NK_VERTEX_LAYOUT_END}
932  * };
933  * cfg.shape_AA = NK_ANTI_ALIASING_ON;
934  * cfg.line_AA = NK_ANTI_ALIASING_ON;
935  * cfg.vertex_layout = vertex_layout;
936  * cfg.vertex_size = sizeof(struct your_vertex);
937  * cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
938  * cfg.circle_segment_count = 22;
939  * cfg.curve_segment_count = 22;
940  * cfg.arc_segment_count = 22;
941  * cfg.global_alpha = 1.0f;
942  * cfg.null = dev->null;
943  *
944  * struct nk_buffer cmds, verts, idx;
945  * nk_buffer_init_default(&cmds);
946  * nk_buffer_init_default(&verts);
947  * nk_buffer_init_default(&idx);
948  * nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
949  * nk_draw_foreach(cmd, &ctx, &cmds) {
950  * if (!cmd->elem_count) continue;
951  * [...]
952  * }
953  * nk_buffer_free(&cms);
954  * nk_buffer_free(&verts);
955  * nk_buffer_free(&idx);
956  *
957  * Reference
958  * -------------------
959  * nk__begin - Returns the first draw command in the context draw command list to be drawn
960  * nk__next - Increments the draw command iterator to the next command inside the context draw command list
961  * nk_foreach - Iteratates over each draw command inside the context draw command list
962  *
963  * nk_convert - Converts from the abstract draw commands list into a hardware accessable vertex format
964  * nk__draw_begin - Returns the first vertex command in the context vertex draw list to be executed
965  * nk__draw_next - Increments the vertex command iterator to the next command inside the context vertex command list
966  * nk__draw_end - Returns the end of the vertex draw list
967  * nk_draw_foreach - Iterates over each vertex draw command inside the vertex draw list
968  */
976 };
978  nk_handle texture; /* texture handle to a texture with a white pixel */
979  struct nk_vec2 uv; /* coordinates to a white pixel in the texture */
980 };
982  float global_alpha; /* global alpha value */
983  enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
984  enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
985  unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
986  unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
987  unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
988  struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
989  const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
990  nk_size vertex_size; /* sizeof one vertex for vertex packing */
991  nk_size vertex_alignment; /* vertex alignment: Can be optained by NK_ALIGNOF */
992 };
993 /* nk__begin - Returns a draw command list iterator to iterate all draw
994  * commands accumulated over one frame.
995  * Parameters:
996  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
997  * Return values:
998  * draw command pointer pointing to the first command inside the draw command list */
999 NK_API const struct nk_command* nk__begin(struct nk_context*);
1000 /* nk__next - Returns a draw command list iterator to iterate all draw
1001  * Parameters:
1002  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1003  * @cmd must point to an previously a draw command either returned by `nk__begin` or `nk__next`
1004  * Return values:
1005  * draw command pointer pointing to the next command inside the draw command list */
1006 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1007 /* nk_foreach - Iterates over each draw command inside the context draw command list
1008  * Parameters:
1009  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1010  * @cmd pointer initialized to NULL */
1011 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1012 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1013 /* nk_convert - converts all internal draw command into vertex draw commands and fills
1014  * three buffers with vertexes, vertex draw commands and vertex indicies. The vertex format
1015  * as well as some other configuration values have to be configurated by filling out a
1016  * `nk_convert_config` struct.
1017  * Parameters:
1018  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1019  * @cmds must point to a previously initialized buffer to hold converted vertex draw commands
1020  * @vertices must point to a previously initialized buffer to hold all produced verticies
1021  * @elements must point to a previously initialized buffer to hold all procudes vertex indicies
1022  * @config must point to a filled out `nk_config` struct to configure the conversion process
1023  * Returns:
1024  * returns NK_CONVERT_SUCCESS on success and a enum nk_convert_result error values if not */
1025 NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1026 /* nk__draw_begin - Returns a draw vertex command buffer iterator to iterate each the vertex draw command buffer
1027  * Parameters:
1028  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1029  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1030  * Return values:
1031  * vertex draw command pointer pointing to the first command inside the vertex draw command buffer */
1032 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1033 /* nk__draw_end - Returns the vertex draw command at the end of the vertex draw command buffer
1034  * Parameters:
1035  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1036  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1037  * Return values:
1038  * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */
1039 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1040 /* nk__draw_next - Increments the the vertex draw command buffer iterator
1041  * Parameters:
1042  * @cmd must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
1043  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1044  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1045  * Return values:
1046  * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */
1047 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1048 /* nk_draw_foreach - Iterates over each vertex draw command inside a vertex draw command buffer
1049  * Parameters:
1050  * @cmd nk_draw_command pointer set to NULL
1051  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1052  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame */
1053 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1054 #endif
1055 /* =============================================================================
1056  *
1057  * WINDOW
1058  *
1059  * =============================================================================
1060  * Windows are the main persistent state used inside nuklear and are life time
1061  * controlled by simply "retouching" (i.e. calling) each window each frame.
1062  * All widgets inside nuklear can only be added inside function pair `nk_begin_xxx`
1063  * and `nk_end`. Calling any widgets outside these two functions will result in an
1064  * assert in debug or no state change in release mode.
1065  *
1066  * Each window holds frame persistent state like position, size, flags, state tables,
1067  * and some garbage collected internal persistent widget state. Each window
1068  * is linked into a window stack list which determines the drawing and overlapping
1069  * order. The topmost window thereby is the currently active window.
1070  *
1071  * To change window position inside the stack occurs either automatically by
1072  * user input by being clicked on or programatically by calling `nk_window_focus`.
1073  * Windows by default are visible unless explicitly being defined with flag
1074  * `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
1075  * `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
1076  * `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.
1077  *
1078  * Usage
1079  * -------------------
1080  * To create and keep a window you have to call one of the two `nk_begin_xxx`
1081  * functions to start window declarations and `nk_end` at the end. Furthermore it
1082  * is recommended to check the return value of `nk_begin_xxx` and only process
1083  * widgets inside the window if the value is not 0. Either way you have to call
1084  * `nk_end` at the end of window declarations. Furthmore do not attempt to
1085  * nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
1086  * in a segmation fault.
1087  *
1088  * if (nk_begin_xxx(...) {
1089  * [... widgets ...]
1090  * }
1091  * nk_end(ctx);
1092  *
1093  * In the grand concept window and widget declarations need to occur after input
1094  * handling and before drawing to screen. Not doing so can result in higher
1095  * latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
1096  * is called at the end of the frame. While nuklears default platform backends
1097  * already call `nk_clear` for you if you write your own backend not calling
1098  * `nk_clear` can cause asserts or even worse undefined behavior.
1099  *
1100  * struct nk_context ctx;
1101  * nk_init_xxx(&ctx, ...);
1102  * while (1) {
1103  * Event evt;
1104  * nk_input_begin(&ctx);
1105  * while (GetEvent(&evt)) {
1106  * if (evt.type == MOUSE_MOVE)
1107  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
1108  * else if (evt.type == [...]) {
1109  * nk_input_xxx(...);
1110  * }
1111  * }
1112  * nk_input_end(&ctx);
1113  *
1114  * if (nk_begin_xxx(...) {
1115  * [...]
1116  * }
1117  * nk_end(ctx);
1118  *
1119  * const struct nk_command *cmd = 0;
1120  * nk_foreach(cmd, &ctx) {
1121  * case NK_COMMAND_LINE:
1122  * your_draw_line_function(...)
1123  * break;
1124  * case NK_COMMAND_RECT
1125  * your_draw_rect_function(...)
1126  * break;
1127  * case ...:
1128  * [...]
1129  * }
1130  * nk_clear(&ctx);
1131  * }
1132  * nk_free(&ctx);
1133  *
1134  * Reference
1135  * -------------------
1136  * nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1137  * nk_begin_titled - extended window start with seperated title and identifier to allow multiple windows with same name but not title
1138  * nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
1139  *
1140  * nk_window_find - finds and returns the window with give name
1141  * nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1142  * nk_window_get_position - returns the position of the currently processed window
1143  * nk_window_get_size - returns the size with width and height of the currently processed window
1144  * nk_window_get_width - returns the width of the currently processed window
1145  * nk_window_get_height - returns the height of the currently processed window
1146  * nk_window_get_panel - returns the underlying panel which contains all processing state of the currnet window
1147  * nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window
1148  * nk_window_get_content_region_min - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1149  * nk_window_get_content_region_max - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1150  * nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1151  * nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1152  *
1153  * nk_window_has_focus - returns if the currently processed window is currently active
1154  * nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1155  * nk_window_is_closed - returns if the currently processed window was closed
1156  * nk_window_is_hidden - returns if the currently processed window was hidden
1157  * nk_window_is_active - same as nk_window_has_focus for some reason
1158  * nk_window_is_hovered - returns if the currently processed window is currently being hovered by mouse
1159  * nk_window_is_any_hovered - return if any wndow currently hovered
1160  * nk_item_is_any_active - returns if any window or widgets is currently hovered or active
1161  *
1162  * nk_window_set_bounds - updates position and size of the currently processed window
1163  * nk_window_set_position - updates position of the currently process window
1164  * nk_window_set_size - updates the size of the currently processed window
1165  * nk_window_set_focus - set the currently processed window as active window
1166  *
1167  * nk_window_close - closes the window with given window name which deletes the window at the end of the frame
1168  * nk_window_collapse - collapses the window with given window name
1169  * nk_window_collapse_if - collapses the window with given window name if the given condition was met
1170  * nk_window_show - hides a visible or reshows a hidden window
1171  * nk_window_show_if - hides/shows a window depending on condition
1172  */
1174  NK_WINDOW_BORDER = NK_FLAG(0), /* Draws a border around the window to visually separate window from the background */
1175  NK_WINDOW_MOVABLE = NK_FLAG(1), /* The movable flag indicates that a window can be moved by user input or by dragging the window header */
1176  NK_WINDOW_SCALABLE = NK_FLAG(2), /* The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window */
1177  NK_WINDOW_CLOSABLE = NK_FLAG(3), /* adds a closable icon into the header */
1178  NK_WINDOW_MINIMIZABLE = NK_FLAG(4), /* adds a minimize icon into the header */
1179  NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), /* Removes the scrollbar from the window */
1180  NK_WINDOW_TITLE = NK_FLAG(6), /* Forces a header at the top at the window showing the title */
1181  NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), /* Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame */
1182  NK_WINDOW_BACKGROUND = NK_FLAG(8), /* Always keep window in the background */
1183  NK_WINDOW_SCALE_LEFT = NK_FLAG(9), /* Puts window scaler in the left-ottom corner instead right-bottom*/
1184  NK_WINDOW_NO_INPUT = NK_FLAG(10) /* Prevents window of scaling, moving or getting focus */
1185 };
1186 /* nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1187  * Parameters:
1188  * @ctx must point to an previously initialized `nk_context` struct
1189  * @title window title and identifier. Needs to be persitent over frames to identify the window
1190  * @bounds initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
1191  * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1192  * Return values:
1193  * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise for example if minimized `*/
1194 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1195 /* nk_begin_titled - extended window start with seperated title and identifier to allow multiple windows with same name but not title
1196  * Parameters:
1197  * @ctx must point to an previously initialized `nk_context` struct
1198  * @name window identifier. Needs to be persitent over frames to identify the window
1199  * @title window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
1200  * @bounds initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
1201  * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1202  * Return values:
1203  * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise `*/
1204 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1205 /* nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
1206  * All widget calls after this functions will result in asserts or no state changes
1207  * Parameters:
1208  * @ctx must point to an previously initialized `nk_context` struct */
1209 NK_API void nk_end(struct nk_context *ctx);
1210 /* nk_window_find - finds and returns the window with give name
1211  * Parameters:
1212  * @ctx must point to an previously initialized `nk_context` struct
1213  * @name window identifier
1214  * Return values:
1215  * returns a `nk_window` struct pointing to the idified window or 0 if no window with given name was found */
1216 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1217 /* nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1218  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1219  * Parameters:
1220  * @ctx must point to an previously initialized `nk_context` struct
1221  * Return values:
1222  * returns a `nk_rect` struct with window upper left position and size */
1224 /* nk_window_get_position - returns the position of the currently processed window.
1225  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1226  * Parameters:
1227  * @ctx must point to an previously initialized `nk_context` struct
1228  * Return values:
1229  * returns a `nk_vec2` struct with window upper left position */
1231 /* nk_window_get_size - returns the size with width and height of the currently processed window.
1232  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1233  * Parameters:
1234  * @ctx must point to an previously initialized `nk_context` struct
1235  * Return values:
1236  * returns a `nk_vec2` struct with window size */
1238 /* nk_window_get_width - returns the width of the currently processed window.
1239  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1240  * Parameters:
1241  * @ctx must point to an previously initialized `nk_context` struct
1242  * Return values:
1243  * returns the window width */
1244 NK_API float nk_window_get_width(const struct nk_context*);
1245 /* nk_window_get_height - returns the height of the currently processed window.
1246  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1247  * Parameters:
1248  * @ctx must point to an previously initialized `nk_context` struct
1249  * Return values:
1250  * returns the window height */
1251 NK_API float nk_window_get_height(const struct nk_context*);
1252 /* nk_window_get_panel - returns the underlying panel which contains all processing state of the currnet window.
1253  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1254  * Parameters:
1255  * @ctx must point to an previously initialized `nk_context` struct
1256  * Return values:
1257  * returns a pointer to window internal `nk_panel` state. DO NOT keep this pointer around it is only valid until `nk_end` */
1259 /* nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window.
1260  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1261  * Parameters:
1262  * @ctx must point to an previously initialized `nk_context` struct
1263  * Return values:
1264  * returns `nk_rect` struct with screen position and size (no scrollbar offset) of the visible space inside the current window */
1266 /* nk_window_get_content_region_min - returns the upper left position of the currently visible and non-clipped space inside the currently processed window.
1267  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1268  * Parameters:
1269  * @ctx must point to an previously initialized `nk_context` struct
1270  * Return values:
1271  * returns `nk_vec2` struct with upper left screen position (no scrollbar offset) of the visible space inside the current window */
1273 /* nk_window_get_content_region_max - returns the lower right screen position of the currently visible and non-clipped space inside the currently processed window.
1274  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1275  * Parameters:
1276  * @ctx must point to an previously initialized `nk_context` struct
1277  * Return values:
1278  * returns `nk_vec2` struct with lower right screen position (no scrollbar offset) of the visible space inside the current window */
1280 /* nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1281  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1282  * Parameters:
1283  * @ctx must point to an previously initialized `nk_context` struct
1284  * Return values:
1285  * returns `nk_vec2` struct with size the visible space inside the current window */
1287 /* nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1288  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1289  * Parameters:
1290  * @ctx must point to an previously initialized `nk_context` struct
1291  * Return values:
1292  * returns a pointer to window internal `nk_command_buffer` struct used as drawing canvas. Can be used to do custom drawing */
1294 /* nk_window_has_focus - returns if the currently processed window is currently active
1295  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1296  * Parameters:
1297  * @ctx must point to an previously initialized `nk_context` struct
1298  * Return values:
1299  * returns 0 if current window is not active or 1 if it is */
1300 NK_API int nk_window_has_focus(const struct nk_context*);
1301 /* nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1302  * Parameters:
1303  * @ctx must point to an previously initialized `nk_context` struct
1304  * @name of window you want to check is collapsed
1305  * Return values:
1306  * returns 1 if current window is minimized and 0 if window not found or is not minimized */
1307 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1308 /* nk_window_is_closed - returns if the window with given name was closed by calling `nk_close`
1309  * Parameters:
1310  * @ctx must point to an previously initialized `nk_context` struct
1311  * @name of window you want to check is closed
1312  * Return values:
1313  * returns 1 if current window was closed or 0 window not found or not closed */
1314 NK_API int nk_window_is_closed(struct nk_context*, const char*);
1315 /* nk_window_is_hidden - returns if the window with given name is hidden
1316  * Parameters:
1317  * @ctx must point to an previously initialized `nk_context` struct
1318  * @name of window you want to check is hidden
1319  * Return values:
1320  * returns 1 if current window is hidden or 0 window not found or visible */
1321 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1322 /* nk_window_is_active - same as nk_window_has_focus for some reason
1323  * Parameters:
1324  * @ctx must point to an previously initialized `nk_context` struct
1325  * @name of window you want to check is hidden
1326  * Return values:
1327  * returns 1 if current window is active or 0 window not found or not active */
1328 NK_API int nk_window_is_active(struct nk_context*, const char*);
1329 /* nk_window_is_hovered - return if the current window is being hovered
1330  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1331  * Parameters:
1332  * @ctx must point to an previously initialized `nk_context` struct
1333  * Return values:
1334  * returns 1 if current window is hovered or 0 otherwise */
1336 /* nk_window_is_any_hovered - returns if the any window is being hovered
1337  * Parameters:
1338  * @ctx must point to an previously initialized `nk_context` struct
1339  * Return values:
1340  * returns 1 if any window is hovered or 0 otherwise */
1342 /* nk_item_is_any_active - returns if the any window is being hovered or any widget is currently active.
1343  * Can be used to decide if input should be processed by UI or your specific input handling.
1344  * Example could be UI and 3D camera to move inside a 3D space.
1345  * Parameters:
1346  * @ctx must point to an previously initialized `nk_context` struct
1347  * Return values:
1348  * returns 1 if any window is hovered or any item is active or 0 otherwise */
1350 /* nk_window_set_bounds - updates position and size of the currently processed window
1351  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1352  * Parameters:
1353  * @ctx must point to an previously initialized `nk_context` struct
1354  * @bounds points to a `nk_rect` struct with the new position and size of currently active window */
1355 NK_API void nk_window_set_bounds(struct nk_context*, struct nk_rect bounds);
1356 /* nk_window_set_position - updates position of the currently processed window
1357  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1358  * Parameters:
1359  * @ctx must point to an previously initialized `nk_context` struct
1360  * @pos points to a `nk_vec2` struct with the new position of currently active window */
1361 NK_API void nk_window_set_position(struct nk_context*, struct nk_vec2 pos);
1362 /* nk_window_set_size - updates size of the currently processed window
1363  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1364  * Parameters:
1365  * @ctx must point to an previously initialized `nk_context` struct
1366  * @bounds points to a `nk_vec2` struct with the new size of currently active window */
1367 NK_API void nk_window_set_size(struct nk_context*, struct nk_vec2);
1368 /* nk_window_set_focus - sets the window with given name as active
1369  * Parameters:
1370  * @ctx must point to an previously initialized `nk_context` struct
1371  * @name of the window to be set active */
1372 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1373 /* nk_window_close - closed a window and marks it for being freed at the end of the frame
1374  * Parameters:
1375  * @ctx must point to an previously initialized `nk_context` struct
1376  * @name of the window to be closed */
1377 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1378 /* nk_window_collapse - updates collapse state of a window with given name
1379  * Parameters:
1380  * @ctx must point to an previously initialized `nk_context` struct
1381  * @name of the window to be either collapse or maximize */
1382 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1383 /* nk_window_collapse - updates collapse state of a window with given name if given condition is met
1384  * Parameters:
1385  * @ctx must point to an previously initialized `nk_context` struct
1386  * @name of the window to be either collapse or maximize
1387  * @state the window should be put into
1388  * @condition that has to be true to actually commit the collsage state change */
1389 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1390 /* nk_window_show - updates visibility state of a window with given name
1391  * Parameters:
1392  * @ctx must point to an previously initialized `nk_context` struct
1393  * @name of the window to be either collapse or maximize
1394  * @state with either visible or hidden to modify the window with */
1395 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1396 /* nk_window_show_if - updates visibility state of a window with given name if a given condition is met
1397  * Parameters:
1398  * @ctx must point to an previously initialized `nk_context` struct
1399  * @name of the window to be either collapse or maximize
1400  * @state with either visible or hidden to modify the window with
1401  * @condition that has to be true to actually commit the visible state change */
1402 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1403 /* =============================================================================
1404  *
1405  * LAYOUT
1406  *
1407  * ============================================================================= */
1408 /* Layouting in general describes placing widget inside a window with position and size.
1409  * While in this particular implementation there are five different APIs for layouting
1410  * each with different trade offs between control and ease of use.
1411  *
1412  * All layouting methodes in this library are based around the concept of a row.
1413  * A row has a height the window content grows by and a number of columns and each
1414  * layouting method specifies how each widget is placed inside the row.
1415  * After a row has been allocated by calling a layouting functions and then
1416  * filled with widgets will advance an internal pointer over the allocated row.
1417  *
1418  * To acually define a layout you just call the appropriate layouting function
1419  * and each subsequnetial widget call will place the widget as specified. Important
1420  * here is that if you define more widgets then columns defined inside the layout
1421  * functions it will allocate the next row without you having to make another layouting
1422  * call.
1423  *
1424  * Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
1425  * is that you have to define the row height for each. However the row height
1426  * often depends on the height of the font. So I would recommend writing
1427  * a higher level layouting functions that just calls each function with default font height
1428  * plus some spacing between rows. The reason why this library does't support this
1429  * behavior by default is to grant more control.
1430  *
1431  * For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
1432  * layouting method in combination with a cassowary constraint solver (there are
1433  * some versions on github with permissive license model) to take over all control over widget
1434  * layouting yourself. However for quick and dirty layouting using all the other layouting
1435  * functions, especially if you don't change the font height, should be fine.
1436  *
1437  * Usage
1438  * -------------------
1439  * 1.) nk_layout_row_dynamic
1440  * The easiest layouting function is `nk_layout_row_dynamic`. It provides each
1441  * widgets with same horizontal space inside the row and dynamically grows
1442  * if the owning window grows in width. So the number of columns dictates
1443  * the size of each widget dynamically by formula:
1444  *
1445  * widget_width = (window_width - padding - spacing) * (1/colum_count)
1446  *
1447  * Just like all other layouting APIs if you define more widget than columns this
1448  * library will allocate a new row and keep all layouting parameters previously
1449  * defined.
1450  *
1451  * if (nk_begin_xxx(...) {
1452  * // first row with height: 30 composed of two widgets
1453  * nk_layout_row_dynamic(&ctx, 30, 2);
1454  * nk_widget(...);
1455  * nk_widget(...);
1456  *
1457  * // second row with same parameter as defined above
1458  * nk_widget(...);
1459  * nk_widget(...);
1460  * }
1461  * nk_end(...);
1462  *
1463  * 2.) nk_layout_row_static
1464  * Another easy layouting function is `nk_layout_row_static`. It provides each
1465  * widget with same horizontal pixel width inside the row and does not grow
1466  * if the owning window scales smaller or bigger.
1467  *
1468  * if (nk_begin_xxx(...) {
1469  * // first row with height: 30 composed of two widgets with width: 80
1470  * nk_layout_row_static(&ctx, 30, 80, 2);
1471  * nk_widget(...);
1472  * nk_widget(...);
1473  *
1474  * // second row with same parameter as defined above
1475  * nk_widget(...);
1476  * nk_widget(...);
1477  * }
1478  * nk_end(...);
1479  *
1480  * 3.) nk_layout_row_xxx
1481  * A little bit more advanced layouting API are functions `nk_layout_row_begin`,
1482  * `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
1483  * specify each column pixel or window ratio in a row. It support either
1484  * directly setting per column pixel width or widget window ratio but not
1485  * both. Furthermore it is a immediate mode API so each value is directly
1486  * pushed before calling a widget. Therefore the layout is not automatically
1487  * repeating like the last two layouting functions.
1488  *
1489  * if (nk_begin_xxx(...) {
1490  * // first row with height: 25 composed of two widgets with width 60 and 40
1491  * nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
1492  * nk_layout_row_push(ctx, 60);
1493  * nk_widget(...);
1494  * nk_layout_row_push(ctx, 40);
1495  * nk_widget(...);
1496  * nk_layout_row_end(ctx);
1497  *
1498  * // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
1499  * nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
1500  * nk_layout_row_push(ctx, 0.25f);
1501  * nk_widget(...);
1502  * nk_layout_row_push(ctx, 0.75f);
1503  * nk_widget(...);
1504  * nk_layout_row_end(ctx);
1505  * }
1506  * nk_end(...);
1507  *
1508  * 4.) nk_layout_row
1509  * The retain mode counterpart to API nk_layout_row_xxx is the single nk_layout_row
1510  * functions. Instead of pushing either pixel or window ratio for every widget
1511  * it allows to define it by array. The trade of for less control is that
1512  * `nk_layout_row` is automatically repeating. Otherwise the behavior is the
1513  * same.
1514  *
1515  * if (nk_begin_xxx(...) {
1516  * // two rows with height: 30 composed of two widgets with width 60 and 40
1517  * const float size[] = {60,40};
1518  * nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
1519  * nk_widget(...);
1520  * nk_widget(...);
1521  * nk_widget(...);
1522  * nk_widget(...);
1523  *
1524  * // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
1525  * const float ratio[] = {0.25, 0.75};
1526  * nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
1527  * nk_widget(...);
1528  * nk_widget(...);
1529  * nk_widget(...);
1530  * nk_widget(...);
1531  * }
1532  * nk_end(...);
1533  *
1534  * 5.) nk_layout_row_template_xxx
1535  * The most complex and second most flexible API is a simplified flexbox version without
1536  * line wrapping and weights for dynamic widgets. It is an immediate mode API but
1537  * unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
1538  * before calling the templated widgets.
1539  * The row template layout has three different per widget size specifier. The first
1540  * one is the static widget size specifier with fixed widget pixel width. They do
1541  * not grow if the row grows and will always stay the same. The second size
1542  * specifier is nk_layout_row_template_push_variable which defines a
1543  * minumum widget size but it also can grow if more space is available not taken
1544  * by other widgets. Finally there are dynamic widgets which are completly flexible
1545  * and unlike variable widgets can even shrink to zero if not enough space
1546  * is provided.
1547  *
1548  * if (nk_begin_xxx(...) {
1549  * // two rows with height: 30 composed of three widgets
1550  * nk_layout_row_template_begin(ctx, 30);
1551  * nk_layout_row_template_push_dynamic(ctx);
1552  * nk_layout_row_template_push_variable(ctx, 80);
1553  * nk_layout_row_template_push_static(ctx, 80);
1554  * nk_layout_row_template_end(ctx);
1555  *
1556  * nk_widget(...); // dynamic widget completly can go to zero
1557  * nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
1558  * nk_widget(...); // static widget with fixed 80 pixel width
1559  * }
1560  * nk_end(...);
1561  *
1562  * 6.) nk_layout_space_xxx
1563  * Finally the most flexible API directly allows you to place widgets inside the
1564  * window. The space layout API is an immediate mode API which does not support
1565  * row auto repeat and directly sets position and size of a widget. Position
1566  * and size hereby can be either specified as ratio of alloated space or
1567  * allocated space local position and pixel size. Since this API is quite
1568  * powerfull there are a number of utility functions to get the available space
1569  * and convert between local allocated space and screen space.
1570  *
1571  * if (nk_begin_xxx(...) {
1572  * // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1573  * nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
1574  * nk_layout_space_push(ctx, nk_rect(0,0,150,200));
1575  * nk_widget(...);
1576  * nk_layout_space_push(ctx, nk_rect(200,200,100,200));
1577  * nk_widget(...);
1578  * nk_layout_space_end(ctx);
1579  *
1580  * // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1581  * nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
1582  * nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
1583  * nk_widget(...);
1584  * nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
1585  * nk_widget(...);
1586  * }
1587  * nk_end(...);
1588  *
1589  * Reference
1590  * -------------------
1591  * nk_layout_row_dynamic - current layout is divided into n same sized gowing columns
1592  * nk_layout_row_static - current layout is divided into n same fixed sized columns
1593  * nk_layout_row_begin - starts a new row with given height and number of columns
1594  * nk_layout_row_push - pushes another column with given size or window ratio
1595  * nk_layout_row_end - finished previously started row
1596  * nk_layout_row - specifies row columns in array as either window ratio or size
1597  *
1598  * nk_layout_row_template_begin
1599  * nk_layout_row_template_push_dynamic
1600  * nk_layout_row_template_push_variable
1601  * nk_layout_row_template_push_static
1602  * nk_layout_row_template_end
1603  *
1604  * nk_layout_space_begin
1605  * nk_layout_space_push
1606  * nk_layout_space_end
1607  *
1608  * nk_layout_space_bounds
1609  * nk_layout_space_to_screen
1610  * nk_layout_space_to_local
1611  * nk_layout_space_rect_to_screen
1612  * nk_layout_space_rect_to_local
1613  * nk_layout_ratio_from_pixel
1614  */
1615 /* nk_layout_row_dynamic - Sets current row layout to share horizontal space
1616  * between @cols number of widgets evenly. Once called all subsequent widget
1617  * calls greater than @cols will allocate a new row with same layout.
1618  * Parameters:
1619  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1620  * @height holds row height to allocate from panel for widget height
1621  * @cols number of widget inside row */
1622 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
1623 /* nk_layout_row_static - Sets current row layout to fill @cols number of widgets
1624  * in row with same @item_width horizontal size. Once called all subsequent widget
1625  * calls greater than @cols will allocate a new row with same layout.
1626  * Parameters:
1627  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1628  * @height holds row height to allocate from panel for widget height
1629  * @item_width holds width of each widget in row
1630  * @cols number of widget inside row */
1631 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
1632 /* nk_layout_row_begin - Starts a new dynamic or fixed row with given height and columns.
1633  * Parameters:
1634  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1635  * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1636  * @row_height holds width of each widget in row
1637  * @cols number of widget inside row */
1638 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
1639 /* nk_layout_row_push - Specifies either window ratio or width of a single column
1640  * Parameters:
1641  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin`
1642  * @value either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call */
1643 NK_API void nk_layout_row_push(struct nk_context*, float value);
1644 NK_API void nk_layout_row_end(struct nk_context*);
1645 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
1646 
1647 NK_API void nk_layout_row_template_begin(struct nk_context*, float height);
1649 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
1650 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
1652 
1653 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
1654 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect);
1655 NK_API void nk_layout_space_end(struct nk_context*);
1656 
1659 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
1662 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
1663 /* =============================================================================
1664  *
1665  * GROUP
1666  *
1667  * ============================================================================= */
1668 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
1669 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char*, nk_flags);
1670 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll*, const char *title, nk_flags);
1672 NK_API void nk_group_end(struct nk_context*);
1673 /* =============================================================================
1674  *
1675  * LIST VIEW
1676  *
1677  * ============================================================================= */
1679 /* public: */
1680  int begin, end, count;
1681 /* private: */
1683  struct nk_context *ctx;
1684  nk_uint *scroll_pointer;
1685  nk_uint scroll_value;
1686 };
1687 NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
1688 NK_API void nk_list_view_end(struct nk_list_view*);
1689 /* =============================================================================
1690  *
1691  * TREE
1692  *
1693  * ============================================================================= */
1694 #define nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
1695 #define nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
1696 NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
1697 #define nk_tree_image_push(ctx, type, img, title, state) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
1698 #define nk_tree_image_push_id(ctx, type, img, title, state, id) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
1699 NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
1700 NK_API void nk_tree_pop(struct nk_context*);
1701 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
1702 NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
1703 NK_API void nk_tree_state_pop(struct nk_context*);
1704 /* =============================================================================
1705  *
1706  * WIDGET
1707  *
1708  * ============================================================================= */
1710  NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
1711  NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
1712  NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
1713 };
1716  NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */
1717  NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */
1718  NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */
1719  NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */
1720  NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
1723 };
1724 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
1726 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
1728 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
1729 NK_API float nk_widget_width(struct nk_context*);
1730 NK_API float nk_widget_height(struct nk_context*);
1733 NK_API int nk_widget_is_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
1734 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
1735 NK_API void nk_spacing(struct nk_context*, int cols);
1736 /* =============================================================================
1737  *
1738  * TEXT
1739  *
1740  * ============================================================================= */
1748 };
1753 };
1754 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
1755 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
1756 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
1757 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
1758 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
1759 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
1760 NK_API void nk_label_wrap(struct nk_context*, const char*);
1761 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
1762 NK_API void nk_image(struct nk_context*, struct nk_image);
1763 #ifdef NK_INCLUDE_STANDARD_VARARGS
1764 NK_API void nk_labelf(struct nk_context*, nk_flags, const char*, ...);
1765 NK_API void nk_labelf_colored(struct nk_context*, nk_flags align, struct nk_color, const char*,...);
1766 NK_API void nk_labelf_wrap(struct nk_context*, const char*,...);
1767 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, const char*,...);
1768 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
1769 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
1770 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
1771 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
1772 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
1773 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
1774 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
1775 #endif
1776 /* =============================================================================
1777  *
1778  * BUTTON
1779  *
1780  * ============================================================================= */
1781 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
1782 NK_API int nk_button_label(struct nk_context*, const char *title);
1783 NK_API int nk_button_color(struct nk_context*, struct nk_color);
1785 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
1786 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
1787 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1788 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
1789 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
1790 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
1791 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
1792 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
1793 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
1794 NK_API int k_button_symbol_label_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, nk_flags text_alignment);
1795 NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1796 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
1797 NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
1798 NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
1802 /* =============================================================================
1803  *
1804  * CHECKBOX
1805  *
1806  * ============================================================================= */
1807 NK_API int nk_check_label(struct nk_context*, const char*, int active);
1808 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
1809 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
1810 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
1811 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
1812 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
1813 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
1814 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
1815 /* =============================================================================
1816  *
1817  * RADIO BUTTON
1818  *
1819  * ============================================================================= */
1820 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
1821 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
1822 NK_API int nk_option_label(struct nk_context*, const char*, int active);
1823 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
1824 /* =============================================================================
1825  *
1826  * SELECTABLE
1827  *
1828  * ============================================================================= */
1829 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
1830 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
1831 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value);
1832 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
1833 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
1834 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
1835 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
1836 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
1837 /* =============================================================================
1838  *
1839  * SLIDER
1840  *
1841  * ============================================================================= */
1842 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
1843 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
1844 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
1845 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
1846 /* =============================================================================
1847  *
1848  * PROGRESSBAR
1849  *
1850  * ============================================================================= */
1851 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
1852 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
1853 
1854 /* =============================================================================
1855  *
1856  * COLOR PICKER
1857  *
1858  * ============================================================================= */
1859 NK_API struct nk_color nk_color_picker(struct nk_context*, struct nk_color, enum nk_color_format);
1860 NK_API int nk_color_pick(struct nk_context*, struct nk_color*, enum nk_color_format);
1861 /* =============================================================================
1862  *
1863  * PROPERTIES
1864  *
1865  * ============================================================================= */
1866 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
1867 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
1868 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
1869 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
1870 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
1871 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
1872 /* =============================================================================
1873  *
1874  * TEXT EDIT
1875  *
1876  * ============================================================================= */
1891 };
1897 };
1899  NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */
1900  NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */
1901  NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */
1902  NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
1903  NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */
1904 };
1905 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
1906 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
1907 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
1908 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
1909 NK_API void nk_edit_unfocus(struct nk_context*);
1910 /* =============================================================================
1911  *
1912  * CHART
1913  *
1914  * ============================================================================= */
1915 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
1916 NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
1917 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
1918 NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value);
1919 NK_API nk_flags nk_chart_push(struct nk_context*, float);
1920 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
1921 NK_API void nk_chart_end(struct nk_context*);
1922 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
1923 NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset);
1924 /* =============================================================================
1925  *
1926  * POPUP
1927  *
1928  * ============================================================================= */
1929 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
1930 NK_API void nk_popup_close(struct nk_context*);
1931 NK_API void nk_popup_end(struct nk_context*);
1932 /* =============================================================================
1933  *
1934  * COMBOBOX
1935  *
1936  * ============================================================================= */
1937 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
1938 NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size);
1939 NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size);
1940 NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size);
1941 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
1942 NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size);
1943 NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator,int *selected, int count, int item_height, struct nk_vec2 size);
1944 NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size);
1945 /* =============================================================================
1946  *
1947  * ABSTRACT COMBOBOX
1948  *
1949  * ============================================================================= */
1950 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
1951 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
1952 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
1953 NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size);
1954 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
1955 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
1956 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size);
1957 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
1958 NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size);
1959 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
1960 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
1961 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
1962 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
1963 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
1964 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1965 NK_API void nk_combo_close(struct nk_context*);
1966 NK_API void nk_combo_end(struct nk_context*);
1967 /* =============================================================================
1968  *
1969  * CONTEXTUAL
1970  *
1971  * ============================================================================= */
1972 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
1973 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
1974 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
1975 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
1976 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
1977 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
1978 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1979 NK_API void nk_contextual_close(struct nk_context*);
1980 NK_API void nk_contextual_end(struct nk_context*);
1981 /* =============================================================================
1982  *
1983  * TOOLTIP
1984  *
1985  * ============================================================================= */
1986 NK_API void nk_tooltip(struct nk_context*, const char*);
1987 NK_API int nk_tooltip_begin(struct nk_context*, float width);
1988 NK_API void nk_tooltip_end(struct nk_context*);
1989 /* =============================================================================
1990  *
1991  * MENU
1992  *
1993  * ============================================================================= */
1994 NK_API void nk_menubar_begin(struct nk_context*);
1995 NK_API void nk_menubar_end(struct nk_context*);
1996 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
1997 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
1998 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
1999 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
2000 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
2001 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
2002 NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2003 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2004 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
2005 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
2006 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2007 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
2008 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2009 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2010 NK_API void nk_menu_close(struct nk_context*);
2011 NK_API void nk_menu_end(struct nk_context*);
2012 /* =============================================================================
2013  *
2014  * STYLE
2015  *
2016  * ============================================================================= */
2047 };
2057 };
2058 NK_API void nk_style_default(struct nk_context*);
2059 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
2060 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
2061 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
2063 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
2065 NK_API void nk_style_show_cursor(struct nk_context*);
2066 NK_API void nk_style_hide_cursor(struct nk_context*);
2067 
2068 NK_API int nk_style_push_font(struct nk_context*, struct nk_user_font*);
2069 NK_API int nk_style_push_float(struct nk_context*, float*, float);
2070 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
2072 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
2073 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
2074 
2075 NK_API int nk_style_pop_font(struct nk_context*);
2076 NK_API int nk_style_pop_float(struct nk_context*);
2077 NK_API int nk_style_pop_vec2(struct nk_context*);
2079 NK_API int nk_style_pop_flags(struct nk_context*);
2080 NK_API int nk_style_pop_color(struct nk_context*);
2081 /* =============================================================================
2082  *
2083  * COLOR
2084  *
2085  * ============================================================================= */
2086 NK_API struct nk_color nk_rgb(int r, int g, int b);
2087 NK_API struct nk_color nk_rgb_iv(const int *rgb);
2088 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
2089 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
2090 NK_API struct nk_color nk_rgb_fv(const float *rgb);
2091 NK_API struct nk_color nk_rgb_hex(const char *rgb);
2092 
2093 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
2094 NK_API struct nk_color nk_rgba_u32(nk_uint);
2095 NK_API struct nk_color nk_rgba_iv(const int *rgba);
2096 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
2097 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
2098 NK_API struct nk_color nk_rgba_fv(const float *rgba);
2099 NK_API struct nk_color nk_rgba_hex(const char *rgb);
2100 
2101 NK_API struct nk_color nk_hsv(int h, int s, int v);
2102 NK_API struct nk_color nk_hsv_iv(const int *hsv);
2103 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
2104 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
2105 NK_API struct nk_color nk_hsv_fv(const float *hsv);
2106 
2107 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
2108 NK_API struct nk_color nk_hsva_iv(const int *hsva);
2109 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
2110 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
2111 NK_API struct nk_color nk_hsva_fv(const float *hsva);
2112 
2113 /* color (conversion nuklear --> user) */
2114 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
2115 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
2116 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
2117 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
2118 
2119 NK_API nk_uint nk_color_u32(struct nk_color);
2120 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
2121 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
2122 
2123 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
2124 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
2125 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
2126 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
2127 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
2128 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
2129 
2130 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
2131 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
2132 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
2133 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
2134 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
2135 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
2136 /* =============================================================================
2137  *
2138  * IMAGE
2139  *
2140  * ============================================================================= */
2141 NK_API nk_handle nk_handle_ptr(void*);
2142 NK_API nk_handle nk_handle_id(int);
2143 NK_API struct nk_image nk_image_handle(nk_handle);
2144 NK_API struct nk_image nk_image_ptr(void*);
2145 NK_API struct nk_image nk_image_id(int);
2146 NK_API int nk_image_is_subimage(const struct nk_image* img);
2147 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
2148 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
2149 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
2150 /* =============================================================================
2151  *
2152  * MATH
2153  *
2154  * ============================================================================= */
2155 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
2156 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
2157 
2158 NK_API struct nk_vec2 nk_vec2(float x, float y);
2159 NK_API struct nk_vec2 nk_vec2i(int x, int y);
2160 NK_API struct nk_vec2 nk_vec2v(const float *xy);
2161 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
2162 
2164 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
2165 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
2166 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
2167 NK_API struct nk_rect nk_rectv(const float *xywh);
2168 NK_API struct nk_rect nk_rectiv(const int *xywh);
2169 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
2170 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
2171 /* =============================================================================
2172  *
2173  * STRING
2174  *
2175  * ============================================================================= */
2176 NK_API int nk_strlen(const char *str);
2177 NK_API int nk_stricmp(const char *s1, const char *s2);
2178 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
2179 NK_API int nk_strtoi(const char *str, const char **endptr);
2180 NK_API float nk_strtof(const char *str, const char **endptr);
2181 NK_API double nk_strtod(const char *str, const char **endptr);
2182 NK_API int nk_strfilter(const char *text, const char *regexp);
2183 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
2184 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
2185 /* =============================================================================
2186  *
2187  * UTF-8
2188  *
2189  * ============================================================================= */
2190 NK_API int nk_utf_decode(const char*, nk_rune*, int);
2191 NK_API int nk_utf_encode(nk_rune, char*, int);
2192 NK_API int nk_utf_len(const char*, int byte_len);
2193 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
2194 /* ===============================================================
2195  *
2196  * FONT
2197  *
2198  * ===============================================================*/
2199 /* Font handling in this library was designed to be quite customizable and lets
2200  you decide what you want to use and what you want to provide. There are three
2201  different ways to use the font atlas. The first two will use your font
2202  handling scheme and only requires essential data to run nuklear. The next
2203  slightly more advanced features is font handling with vertex buffer output.
2204  Finally the most complex API wise is using nuklears font baking API.
2205 
2206  1.) Using your own implementation without vertex buffer output
2207  --------------------------------------------------------------
2208  So first up the easiest way to do font handling is by just providing a
2209  `nk_user_font` struct which only requires the height in pixel of the used
2210  font and a callback to calculate the width of a string. This way of handling
2211  fonts is best fitted for using the normal draw shape command API where you
2212  do all the text drawing yourself and the library does not require any kind
2213  of deeper knowledge about which font handling mechanism you use.
2214  IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
2215  over the complete life time! I know this sucks but it is currently the only
2216  way to switch between fonts.
2217 
2218  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2219  {
2220  your_font_type *type = handle.ptr;
2221  float text_width = ...;
2222  return text_width;
2223  }
2224 
2225  struct nk_user_font font;
2226  font.userdata.ptr = &your_font_class_or_struct;
2227  font.height = your_font_height;
2228  font.width = your_text_width_calculation;
2229 
2230  struct nk_context ctx;
2231  nk_init_default(&ctx, &font);
2232 
2233  2.) Using your own implementation with vertex buffer output
2234  --------------------------------------------------------------
2235  While the first approach works fine if you don't want to use the optional
2236  vertex buffer output it is not enough if you do. To get font handling working
2237  for these cases you have to provide two additional parameters inside the
2238  `nk_user_font`. First a texture atlas handle used to draw text as subimages
2239  of a bigger font atlas texture and a callback to query a character's glyph
2240  information (offset, size, ...). So it is still possible to provide your own
2241  font and use the vertex buffer output.
2242 
2243  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2244  {
2245  your_font_type *type = handle.ptr;
2246  float text_width = ...;
2247  return text_width;
2248  }
2249  void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
2250  {
2251  your_font_type *type = handle.ptr;
2252  glyph.width = ...;
2253  glyph.height = ...;
2254  glyph.xadvance = ...;
2255  glyph.uv[0].x = ...;
2256  glyph.uv[0].y = ...;
2257  glyph.uv[1].x = ...;
2258  glyph.uv[1].y = ...;
2259  glyph.offset.x = ...;
2260  glyph.offset.y = ...;
2261  }
2262 
2263  struct nk_user_font font;
2264  font.userdata.ptr = &your_font_class_or_struct;
2265  font.height = your_font_height;
2266  font.width = your_text_width_calculation;
2267  font.query = query_your_font_glyph;
2268  font.texture.id = your_font_texture;
2269 
2270  struct nk_context ctx;
2271  nk_init_default(&ctx, &font);
2272 
2273  3.) Nuklear font baker
2274  ------------------------------------
2275  The final approach if you do not have a font handling functionality or don't
2276  want to use it in this library is by using the optional font baker.
2277  The font baker API's can be used to create a font plus font atlas texture
2278  and can be used with or without the vertex buffer output.
2279 
2280  It still uses the `nk_user_font` struct and the two different approaches
2281  previously stated still work. The font baker is not located inside
2282  `nk_context` like all other systems since it can be understood as more of
2283  an extension to nuklear and does not really depend on any `nk_context` state.
2284 
2285  Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
2286  functions. If you don't care about memory just call the default version
2287  `nk_font_atlas_init_default` which will allocate all memory from the standard library.
2288  If you want to control memory allocation but you don't care if the allocated
2289  memory is temporary and therefore can be freed directly after the baking process
2290  is over or permanent you can call `nk_font_atlas_init`.
2291 
2292  After successfull intializing the font baker you can add Truetype(.ttf) fonts from
2293  different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
2294  functions. Adding font will permanently store each font, font config and ttf memory block(!)
2295  inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
2296  the font baker by for example adding additional fonts you can call
2297  `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
2298 
2299  As soon as you added all fonts you wanted you can now start the baking process
2300  for every selected glyphes to image by calling `nk_font_atlas_bake`.
2301  The baking process returns image memory, width and height which can be used to
2302  either create your own image object or upload it to any graphics library.
2303  No matter which case you finally have to call `nk_font_atlas_end` which
2304  will free all temporary memory including the font atlas image so make sure
2305  you created our texture beforehand. `nk_font_atlas_end` requires a handle
2306  to your font texture or object and optionally fills a `struct nk_draw_null_texture`
2307  which can be used for the optional vertex output. If you don't want it just
2308  set the argument to `NULL`.
2309 
2310  At this point you are done and if you don't want to reuse the font atlas you
2311  can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
2312  memory. Finally if you don't use the font atlas and any of it's fonts anymore
2313  you need to call `nk_font_atlas_clear` to free all memory still being used.
2314 
2315  struct nk_font_atlas atlas;
2316  nk_font_atlas_init_default(&atlas);
2317  nk_font_atlas_begin(&atlas);
2318  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
2319  nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
2320  const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
2321  nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
2322 
2323  struct nk_context ctx;
2324  nk_init_default(&ctx, &font->handle);
2325  while (1) {
2326 
2327  }
2328  nk_font_atlas_clear(&atlas);
2329 
2330  The font baker API is probably the most complex API inside this library and
2331  I would suggest reading some of my examples `example/` to get a grip on how
2332  to use the font atlas. There are a number of details I left out. For example
2333  how to merge fonts, configure a font with `nk_font_config` to use other languages,
2334  use another texture coodinate format and a lot more:
2335 
2336  struct nk_font_config cfg = nk_font_config(font_pixel_height);
2337  cfg.merge_mode = nk_false or nk_true;
2338  cfg.range = nk_font_korean_glyph_ranges();
2339  cfg.coord_type = NK_COORD_PIXEL;
2340  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
2341 
2342 */
2343 struct nk_user_font_glyph;
2344 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
2345 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
2346  struct nk_user_font_glyph *glyph,
2347  nk_rune codepoint, nk_rune next_codepoint);
2348 
2349 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2350 struct nk_user_font_glyph {
2351  struct nk_vec2 uv[2];
2352  /* texture coordinates */
2353  struct nk_vec2 offset;
2354  /* offset between top left and glyph */
2355  float width, height;
2356  /* size of the glyph */
2357  float xadvance;
2358  /* offset to the next glyph */
2359 };
2360 #endif
2361 
2363  nk_handle userdata;
2364  /* user provided font handle */
2365  float height;
2366  /* max height of the font */
2368  /* font string width in pixel callback */
2369 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2370  nk_query_font_glyph_f query;
2371  /* font glyph callback to query drawing info */
2372  nk_handle texture;
2373  /* texture handle to the used font atlas or texture */
2374 #endif
2375 };
2376 
2377 #ifdef NK_INCLUDE_FONT_BAKING
2378 enum nk_font_coord_type {
2379  NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
2380  NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
2381 };
2382 
2383 struct nk_baked_font {
2384  float height;
2385  /* height of the font */
2386  float ascent, descent;
2387  /* font glyphs ascent and descent */
2388  nk_rune glyph_offset;
2389  /* glyph array offset inside the font glyph baking output array */
2390  nk_rune glyph_count;
2391  /* number of glyphs of this font inside the glyph baking array output */
2392  const nk_rune *ranges;
2393  /* font codepoint ranges as pairs of (from/to) and 0 as last element */
2394 };
2395 
2396 struct nk_font_config {
2397  struct nk_font_config *next;
2398  /* NOTE: only used internally */
2399  void *ttf_blob;
2400  /* pointer to loaded TTF file memory block.
2401  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2402  nk_size ttf_size;
2403  /* size of the loaded TTF file memory block
2404  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2405 
2406  unsigned char ttf_data_owned_by_atlas;
2407  /* used inside font atlas: default to: 0*/
2408  unsigned char merge_mode;
2409  /* merges this font into the last font */
2410  unsigned char pixel_snap;
2411  /* align every character to pixel boundary (if true set oversample (1,1)) */
2412  unsigned char oversample_v, oversample_h;
2413  /* rasterize at hight quality for sub-pixel position */
2414  unsigned char padding[3];
2415 
2416  float size;
2417  /* baked pixel height of the font */
2418  enum nk_font_coord_type coord_type;
2419  /* texture coordinate format with either pixel or UV coordinates */
2420  struct nk_vec2 spacing;
2421  /* extra pixel spacing between glyphs */
2422  const nk_rune *range;
2423  /* list of unicode ranges (2 values per range, zero terminated) */
2424  struct nk_baked_font *font;
2425  /* font to setup in the baking process: NOTE: not needed for font atlas */
2426  nk_rune fallback_glyph;
2427  /* fallback glyph to use if a given rune is not found */
2428 };
2429 
2430 struct nk_font_glyph {
2431  nk_rune codepoint;
2432  float xadvance;
2433  float x0, y0, x1, y1, w, h;
2434  float u0, v0, u1, v1;
2435 };
2436 
2437 struct nk_font {
2438  struct nk_font *next;
2439  struct nk_user_font handle;
2440  struct nk_baked_font info;
2441  float scale;
2442  struct nk_font_glyph *glyphs;
2443  const struct nk_font_glyph *fallback;
2444  nk_rune fallback_codepoint;
2445  nk_handle texture;
2446  struct nk_font_config *config;
2447 };
2448 
2449 enum nk_font_atlas_format {
2450  NK_FONT_ATLAS_ALPHA8,
2451  NK_FONT_ATLAS_RGBA32
2452 };
2453 
2454 struct nk_font_atlas {
2455  void *pixel;
2456  int tex_width;
2457  int tex_height;
2458 
2459  struct nk_allocator permanent;
2460  struct nk_allocator temporary;
2461 
2462  struct nk_recti custom;
2463  struct nk_cursor cursors[NK_CURSOR_COUNT];
2464 
2465  int glyph_count;
2466  struct nk_font_glyph *glyphs;
2467  struct nk_font *default_font;
2468  struct nk_font *fonts;
2469  struct nk_font_config *config;
2470  int font_num;
2471 };
2472 
2473 /* some language glyph codepoint ranges */
2474 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
2475 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
2476 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
2477 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
2478 
2479 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2480 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
2481 #endif
2482 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
2483 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
2484 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
2485 NK_API struct nk_font_config nk_font_config(float pixel_height);
2486 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
2487 #ifdef NK_INCLUDE_DEFAULT_FONT
2488 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
2489 #endif
2490 NK_API struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config);
2491 #ifdef NK_INCLUDE_STANDARD_IO
2492 NK_API struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*);
2493 #endif
2494 NK_API struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*);
2495 NK_API struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config);
2496 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
2497 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
2498 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
2499 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
2500 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
2501 
2502 #endif
2503 
2504 /* ==============================================================
2505  *
2506  * MEMORY BUFFER
2507  *
2508  * ===============================================================*/
2509 /* A basic (double)-buffer with linear allocation and resetting as only
2510  freeing policy. The buffer's main purpose is to control all memory management
2511  inside the GUI toolkit and still leave memory control as much as possible in
2512  the hand of the user while also making sure the library is easy to use if
2513  not as much control is needed.
2514  In general all memory inside this library can be provided from the user in
2515  three different ways.
2516 
2517  The first way and the one providing most control is by just passing a fixed
2518  size memory block. In this case all control lies in the hand of the user
2519  since he can exactly control where the memory comes from and how much memory
2520  the library should consume. Of course using the fixed size API removes the
2521  ability to automatically resize a buffer if not enough memory is provided so
2522  you have to take over the resizing. While being a fixed sized buffer sounds
2523  quite limiting, it is very effective in this library since the actual memory
2524  consumption is quite stable and has a fixed upper bound for a lot of cases.
2525 
2526  If you don't want to think about how much memory the library should allocate
2527  at all time or have a very dynamic UI with unpredictable memory consumption
2528  habits but still want control over memory allocation you can use the dynamic
2529  allocator based API. The allocator consists of two callbacks for allocating
2530  and freeing memory and optional userdata so you can plugin your own allocator.
2531 
2532  The final and easiest way can be used by defining
2533  NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
2534  allocation functions malloc and free and takes over complete control over
2535  memory in this library.
2536 */
2538  void *memory;
2539  unsigned int type;
2540  nk_size size;
2541  nk_size allocated;
2542  nk_size needed;
2543  nk_size calls;
2544 };
2545 
2549 };
2550 
2555 };
2556 
2558  int active;
2559  nk_size offset;
2560 };
2561 
2562 struct nk_memory {void *ptr;nk_size size;};
2563 struct nk_buffer {
2565  /* buffer marker to free a buffer to a certain offset */
2567  /* allocator callback for dynamic buffers */
2569  /* memory management type */
2571  /* memory and size of the current memory block */
2573  /* growing factor for dynamic memory management */
2574  nk_size allocated;
2575  /* total amount of memory allocated */
2576  nk_size needed;
2577  /* totally consumed memory given that enough memory is present */
2578  nk_size calls;
2579  /* number of allocation calls */
2580  nk_size size;
2581  /* current size of the buffer */
2582 };
2583 
2584 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2585 NK_API void nk_buffer_init_default(struct nk_buffer*);
2586 #endif
2587 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
2588 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
2589 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
2590 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
2591 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
2593 NK_API void nk_buffer_clear(struct nk_buffer*);
2594 NK_API void nk_buffer_free(struct nk_buffer*);
2595 NK_API void *nk_buffer_memory(struct nk_buffer*);
2596 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
2597 NK_API nk_size nk_buffer_total(struct nk_buffer*);
2598 
2599 /* ==============================================================
2600  *
2601  * STRING
2602  *
2603  * ===============================================================*/
2604 /* Basic string buffer which is only used in context with the text editor
2605  * to manage and manipulate dynamic or fixed size string content. This is _NOT_
2606  * the default string handling method. The only instance you should have any contact
2607  * with this API is if you interact with an `nk_text_edit` object inside one of the
2608  * copy and paste functions and even there only for more advanced cases. */
2609 struct nk_str {
2611  int len; /* in codepoints/runes/glyphs */
2612 };
2613 
2614 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2615 NK_API void nk_str_init_default(struct nk_str*);
2616 #endif
2617 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
2618 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
2619 NK_API void nk_str_clear(struct nk_str*);
2620 NK_API void nk_str_free(struct nk_str*);
2621 
2622 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
2623 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
2624 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
2625 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
2626 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
2627 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
2628 
2629 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
2630 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
2631 
2632 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
2633 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
2634 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
2635 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
2636 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
2637 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
2638 
2639 NK_API void nk_str_remove_chars(struct nk_str*, int len);
2640 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
2641 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
2642 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
2643 
2644 NK_API char *nk_str_at_char(struct nk_str*, int pos);
2645 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
2646 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
2647 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
2648 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
2649 
2650 NK_API char *nk_str_get(struct nk_str*);
2651 NK_API const char *nk_str_get_const(const struct nk_str*);
2652 NK_API int nk_str_len(struct nk_str*);
2653 NK_API int nk_str_len_char(struct nk_str*);
2654 
2655 /*===============================================================
2656  *
2657  * TEXT EDITOR
2658  *
2659  * ===============================================================*/
2660 /* Editing text in this library is handled by either `nk_edit_string` or
2661  * `nk_edit_buffer`. But like almost everything in this library there are multiple
2662  * ways of doing it and a balance between control and ease of use with memory
2663  * as well as functionality controlled by flags.
2664  *
2665  * This library generally allows three different levels of memory control:
2666  * First of is the most basic way of just providing a simple char array with
2667  * string length. This method is probably the easiest way of handling simple
2668  * user text input. Main upside is complete control over memory while the biggest
2669  * downside in comparsion with the other two approaches is missing undo/redo.
2670  *
2671  * For UIs that require undo/redo the second way was created. It is based on
2672  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
2673  * This is mainly useful if you want something more like a text editor but don't want
2674  * to have a dynamically growing buffer.
2675  *
2676  * The final way is using a dynamically growing nk_text_edit struct, which
2677  * has both a default version if you don't care where memory comes from and an
2678  * allocator version if you do. While the text editor is quite powerful for its
2679  * complexity I would not recommend editing gigabytes of data with it.
2680  * It is rather designed for uses cases which make sense for a GUI library not for
2681  * an full blown text editor.
2682  */
2683 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
2684 #define NK_TEXTEDIT_UNDOSTATECOUNT 99
2685 #endif
2686 
2687 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
2688 #define NK_TEXTEDIT_UNDOCHARCOUNT 999
2689 #endif
2690 
2691 struct nk_text_edit;
2693  nk_handle userdata;
2696 };
2697 
2699  int where;
2703 };
2704 
2708  short undo_point;
2709  short redo_point;
2712 };
2713 
2717 };
2718 
2723 };
2724 
2727  struct nk_str string;
2730 
2731  int cursor;
2734  unsigned char mode;
2735  unsigned char cursor_at_end_of_line;
2736  unsigned char initialized;
2737  unsigned char has_preferred_x;
2738  unsigned char single_line;
2739  unsigned char active;
2740  unsigned char padding1;
2743 };
2744 
2745 /* filter function */
2746 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
2747 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
2748 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
2749 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
2750 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
2751 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
2752 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
2753 
2754 /* text editor */
2755 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2756 NK_API void nk_textedit_init_default(struct nk_text_edit*);
2757 #endif
2758 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
2759 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
2760 NK_API void nk_textedit_free(struct nk_text_edit*);
2761 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
2762 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
2765 NK_API int nk_textedit_cut(struct nk_text_edit*);
2766 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
2767 NK_API void nk_textedit_undo(struct nk_text_edit*);
2768 NK_API void nk_textedit_redo(struct nk_text_edit*);
2769 
2770 /* ===============================================================
2771  *
2772  * DRAWING
2773  *
2774  * ===============================================================*/
2775 /* This library was designed to be render backend agnostic so it does
2776  not draw anything to screen. Instead all drawn shapes, widgets
2777  are made of, are buffered into memory and make up a command queue.
2778  Each frame therefore fills the command buffer with draw commands
2779  that then need to be executed by the user and his own render backend.
2780  After that the command buffer needs to be cleared and a new frame can be
2781  started. It is probably important to note that the command buffer is the main
2782  drawing API and the optional vertex buffer API only takes this format and
2783  converts it into a hardware accessible format.
2784 
2785  To use the command queue to draw your own widgets you can access the
2786  command buffer of each window by calling `nk_window_get_canvas` after
2787  previously having called `nk_begin`:
2788 
2789  void draw_red_rectangle_widget(struct nk_context *ctx)
2790  {
2791  struct nk_command_buffer *canvas;
2792  struct nk_input *input = &ctx->input;
2793  canvas = nk_window_get_canvas(ctx);
2794 
2795  struct nk_rect space;
2796  enum nk_widget_layout_states state;
2797  state = nk_widget(&space, ctx);
2798  if (!state) return;
2799 
2800  if (state != NK_WIDGET_ROM)
2801  update_your_widget_by_user_input(...);
2802  nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
2803  }
2804 
2805  if (nk_begin(...)) {
2806  nk_layout_row_dynamic(ctx, 25, 1);
2807  draw_red_rectangle_widget(ctx);
2808  }
2809  nk_end(..)
2810 
2811  Important to know if you want to create your own widgets is the `nk_widget`
2812  call. It allocates space on the panel reserved for this widget to be used,
2813  but also returns the state of the widget space. If your widget is not seen and does
2814  not have to be updated it is '0' and you can just return. If it only has
2815  to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
2816  update and draw your widget. The reason for seperating is to only draw and
2817  update what is actually neccessary which is crucial for performance.
2818 */
2839 };
2840 
2841 /* command base and header of every command inside the buffer */
2842 struct nk_command {
2844  nk_size next;
2845 #ifdef NK_INCLUDE_COMMAND_USERDATA
2846  nk_handle userdata;
2847 #endif
2848 };
2849 
2852  short x, y;
2853  unsigned short w, h;
2854 };
2855 
2858  unsigned short line_thickness;
2859  struct nk_vec2i begin;
2860  struct nk_vec2i end;
2861  struct nk_color color;
2862 };
2863 
2866  unsigned short line_thickness;
2867  struct nk_vec2i begin;
2868  struct nk_vec2i end;
2869  struct nk_vec2i ctrl[2];
2870  struct nk_color color;
2871 };
2872 
2875  unsigned short rounding;
2876  unsigned short line_thickness;
2877  short x, y;
2878  unsigned short w, h;
2879  struct nk_color color;
2880 };
2881 
2884  unsigned short rounding;
2885  short x, y;
2886  unsigned short w, h;
2887  struct nk_color color;
2888 };
2889 
2892  short x, y;
2893  unsigned short w, h;
2894  struct nk_color left;
2895  struct nk_color top;
2897  struct nk_color right;
2898 };
2899 
2902  unsigned short line_thickness;
2903  struct nk_vec2i a;
2904  struct nk_vec2i b;
2905  struct nk_vec2i c;
2906  struct nk_color color;
2907 };
2908 
2911  struct nk_vec2i a;
2912  struct nk_vec2i b;
2913  struct nk_vec2i c;
2914  struct nk_color color;
2915 };
2916 
2919  short x, y;
2920  unsigned short line_thickness;
2921  unsigned short w, h;
2922  struct nk_color color;
2923 };
2924 
2927  short x, y;
2928  unsigned short w, h;
2929  struct nk_color color;
2930 };
2931 
2934  short cx, cy;
2935  unsigned short r;
2936  unsigned short line_thickness;
2937  float a[2];
2938  struct nk_color color;
2939 };
2940 
2943  short cx, cy;
2944  unsigned short r;
2945  float a[2];
2946  struct nk_color color;
2947 };
2948 
2951  struct nk_color color;
2952  unsigned short line_thickness;
2953  unsigned short point_count;
2954  struct nk_vec2i points[1];
2955 };
2956 
2959  struct nk_color color;
2960  unsigned short point_count;
2961  struct nk_vec2i points[1];
2962 };
2963 
2966  struct nk_color color;
2967  unsigned short line_thickness;
2968  unsigned short point_count;
2969  struct nk_vec2i points[1];
2970 };
2971 
2974  short x, y;
2975  unsigned short w, h;
2976  struct nk_image img;
2977  struct nk_color col;
2978 };
2979 
2980 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
2981  unsigned short w, unsigned short h, nk_handle callback_data);
2984  short x, y;
2985  unsigned short w, h;
2986  nk_handle callback_data;
2988 };
2989 
2992  const struct nk_user_font *font;
2995  short x, y;
2996  unsigned short w, h;
2997  float height;
2998  int length;
2999  char string[1];
3000 };
3001 
3005 };
3006 
3008  struct nk_buffer *base;
3009  struct nk_rect clip;
3011  nk_handle userdata;
3012  nk_size begin, end, last;
3013 };
3014 
3015 /* shape outlines */
3016 NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color);
3017 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
3018 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
3019 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
3020 NK_API void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color);
3021 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
3022 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
3023 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
3024 
3025 /* filled shades */
3026 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
3027 NK_API void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
3028 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
3029 NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color);
3030 NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color);
3031 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
3032 
3033 /* misc */
3034 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
3035 NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color);
3036 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
3037 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
3038 
3039 /* ===============================================================
3040  *
3041  * INPUT
3042  *
3043  * ===============================================================*/
3045  int down;
3046  unsigned int clicked;
3048 };
3049 struct nk_mouse {
3051  struct nk_vec2 pos;
3052  struct nk_vec2 prev;
3053  struct nk_vec2 delta;
3055  unsigned char grab;
3056  unsigned char grabbed;
3057  unsigned char ungrab;
3058 };
3059 
3060 struct nk_key {
3061  int down;
3062  unsigned int clicked;
3063 };
3064 struct nk_keyboard {
3068 };
3069 
3070 struct nk_input {
3072  struct nk_mouse mouse;
3073 };
3074 
3075 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
3076 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3077 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
3078 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3079 NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down);
3080 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
3081 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
3082 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
3083 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
3084 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
3085 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
3086 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
3087 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
3088 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
3089 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
3090 
3091 /* ===============================================================
3092  *
3093  * DRAW LIST
3094  *
3095  * ===============================================================*/
3096 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3097 /* The optional vertex buffer draw list provides a 2D drawing context
3098  with antialiasing functionality which takes basic filled or outlined shapes
3099  or a path and outputs vertexes, elements and draw commands.
3100  The actual draw list API is not required to be used directly while using this
3101  library since converting the default library draw command output is done by
3102  just calling `nk_convert` but I decided to still make this library accessible
3103  since it can be useful.
3104 
3105  The draw list is based on a path buffering and polygon and polyline
3106  rendering API which allows a lot of ways to draw 2D content to screen.
3107  In fact it is probably more powerful than needed but allows even more crazy
3108  things than this library provides by default.
3109 */
3110 typedef nk_ushort nk_draw_index;
3111 enum nk_draw_list_stroke {
3112  NK_STROKE_OPEN = nk_false,
3113  /* build up path has no connection back to the beginning */
3114  NK_STROKE_CLOSED = nk_true
3115  /* build up path has a connection back to the beginning */
3116 };
3117 
3118 enum nk_draw_vertex_layout_attribute {
3119  NK_VERTEX_POSITION,
3120  NK_VERTEX_COLOR,
3121  NK_VERTEX_TEXCOORD,
3122  NK_VERTEX_ATTRIBUTE_COUNT
3123 };
3124 
3125 enum nk_draw_vertex_layout_format {
3126  NK_FORMAT_SCHAR,
3127  NK_FORMAT_SSHORT,
3128  NK_FORMAT_SINT,
3129  NK_FORMAT_UCHAR,
3130  NK_FORMAT_USHORT,
3131  NK_FORMAT_UINT,
3132  NK_FORMAT_FLOAT,
3133  NK_FORMAT_DOUBLE,
3134 
3135 NK_FORMAT_COLOR_BEGIN,
3136  NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
3137  NK_FORMAT_R16G15B16,
3138  NK_FORMAT_R32G32B32,
3139 
3140  NK_FORMAT_R8G8B8A8,
3141  NK_FORMAT_R16G15B16A16,
3142  NK_FORMAT_R32G32B32A32,
3143  NK_FORMAT_R32G32B32A32_FLOAT,
3144  NK_FORMAT_R32G32B32A32_DOUBLE,
3145 
3146  NK_FORMAT_RGB32,
3147  NK_FORMAT_RGBA32,
3148 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
3149  NK_FORMAT_COUNT
3150 };
3151 
3152 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
3153 struct nk_draw_vertex_layout_element {
3154  enum nk_draw_vertex_layout_attribute attribute;
3155  enum nk_draw_vertex_layout_format format;
3156  nk_size offset;
3157 };
3158 
3159 struct nk_draw_command {
3160  unsigned int elem_count;
3161  /* number of elements in the current draw batch */
3162  struct nk_rect clip_rect;
3163  /* current screen clipping rectangle */
3164  nk_handle texture;
3165  /* current texture to set */
3166 #ifdef NK_INCLUDE_COMMAND_USERDATA
3167  nk_handle userdata;
3168 #endif
3169 };
3170 
3171 struct nk_draw_list {
3172  struct nk_rect clip_rect;
3173  struct nk_vec2 circle_vtx[12];
3174  struct nk_convert_config config;
3175 
3176  struct nk_buffer *buffer;
3177  struct nk_buffer *vertices;
3178  struct nk_buffer *elements;
3179 
3180  unsigned int element_count;
3181  unsigned int vertex_count;
3182  unsigned int cmd_count;
3183  nk_size cmd_offset;
3184 
3185  unsigned int path_count;
3186  unsigned int path_offset;
3187 
3188 #ifdef NK_INCLUDE_COMMAND_USERDATA
3189  nk_handle userdata;
3190 #endif
3191 };
3192 
3193 /* draw list */
3194 NK_API void nk_draw_list_init(struct nk_draw_list*);
3195 NK_API void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements);
3196 NK_API void nk_draw_list_clear(struct nk_draw_list*);
3197 
3198 /* drawing */
3199 #define nk_draw_list_foreach(cmd, can, b) for((cmd)=nk__draw_list_begin(can, b); (cmd)!=0; (cmd)=nk__draw_list_next(cmd, b, can))
3200 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
3201 NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*);
3202 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
3203 NK_API void nk_draw_list_clear(struct nk_draw_list *list);
3204 
3205 /* path */
3206 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
3207 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
3208 NK_API void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max);
3209 NK_API void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments);
3210 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
3211 NK_API void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments);
3212 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
3213 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
3214 
3215 /* stroke */
3216 NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness);
3217 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
3218 NK_API void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness);
3219 NK_API void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness);
3220 NK_API void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness);
3221 NK_API void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing);
3222 
3223 /* fill */
3224 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
3225 NK_API void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
3226 NK_API void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color);
3227 NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs);
3228 NK_API void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing);
3229 
3230 /* misc */
3231 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
3232 NK_API void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color);
3233 #ifdef NK_INCLUDE_COMMAND_USERDATA
3234 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
3235 #endif
3236 
3237 #endif
3238 
3239 /* ===============================================================
3240  *
3241  * GUI
3242  *
3243  * ===============================================================*/
3247 };
3248 
3250  struct nk_image image;
3251  struct nk_color color;
3252 };
3253 
3257 };
3258 
3260  struct nk_color color;
3262 };
3263 
3265  /* background */
3270 
3271  /* text */
3276  nk_flags text_alignment;
3277 
3278  /* properties */
3279  float border;
3280  float rounding;
3284 
3285  /* optional user callbacks */
3286  nk_handle userdata;
3288  void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
3289 };
3290 
3292  /* background */
3297 
3298  /* cursor */
3301 
3302  /* text */
3307  nk_flags text_alignment;
3308 
3309  /* properties */
3312  float spacing;
3313  float border;
3314 
3315  /* optional user callbacks */
3316  nk_handle userdata;
3317  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3318  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3319 };
3320 
3322  /* background (inactive) */
3326 
3327  /* background (active) */
3331 
3332  /* text color (inactive) */
3336 
3337  /* text color (active) */
3342  nk_flags text_alignment;
3343 
3344  /* properties */
3345  float rounding;
3349 
3350  /* optional user callbacks */
3351  nk_handle userdata;
3352  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3353  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3354 };
3355 
3357  /* background */
3362 
3363  /* background bar */
3368 
3369  /* cursor */
3373 
3374  /* properties */
3375  float border;
3376  float rounding;
3377  float bar_height;
3381 
3382  /* optional buttons */
3388 
3389  /* optional user callbacks */
3390  nk_handle userdata;
3391  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3392  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3393 };
3394 
3396  /* background */
3401 
3402  /* cursor */
3407 
3408  /* properties */
3409  float rounding;
3410  float border;
3414 
3415  /* optional user callbacks */
3416  nk_handle userdata;
3417  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3418  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3419 };
3420 
3422  /* background */
3427 
3428  /* cursor */
3433 
3434  /* properties */
3435  float border;
3436  float rounding;
3440 
3441  /* optional buttons */
3447 
3448  /* optional user callbacks */
3449  nk_handle userdata;
3450  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3451  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3452 };
3453 
3455  /* background */
3461 
3462  /* cursor */
3467 
3468  /* text (unselected) */
3472 
3473  /* text (selected) */
3478 
3479  /* properties */
3480  float border;
3481  float rounding;
3486 };
3487 
3489  /* background */
3494 
3495  /* text */
3499 
3500  /* symbols */
3503 
3504  /* properties */
3505  float border;
3506  float rounding;
3508 
3512 
3513  /* optional user callbacks */
3514  nk_handle userdata;
3515  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3516  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3517 };
3518 
3520  /* colors */
3524  struct nk_color color;
3525 
3526  /* properties */
3527  float border;
3528  float rounding;
3530 };
3531 
3533  /* background */
3538 
3539  /* label */
3543 
3544  /* symbol */
3548 
3549  /* button */
3554 
3555  /* properties */
3556  float border;
3557  float rounding;
3561 };
3562 
3564  /* background */
3567  struct nk_color text;
3568 
3569  /* button */
3576 
3577  /* properties */
3578  float border;
3579  float rounding;
3580  float indent;
3583 };
3584 
3588 };
3590  /* background */
3594 
3595  /* button */
3601 
3602  /* title */
3606 
3607  /* properties */
3612 };
3613 
3618 
3627 
3628  float border;
3635 
3636  float rounding;
3640 
3648 };
3649 
3650 struct nk_style {
3651  const struct nk_user_font *font;
3653  const struct nk_cursor *cursor_active;
3656 
3674 };
3675 
3679 
3680 /*==============================================================
3681  * PANEL
3682  * =============================================================*/
3683 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
3684 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
3685 #endif
3686 #ifndef NK_CHART_MAX_SLOT
3687 #define NK_CHART_MAX_SLOT 4
3688 #endif
3689 
3698 };
3703 };
3704 
3707  struct nk_color color;
3709  float min, max, range;
3710  int count;
3711  struct nk_vec2 last;
3712  int index;
3713 };
3714 
3715 struct nk_chart {
3716  int slot;
3717  float x, y, w, h;
3719 };
3720 
3732 };
3735  int index;
3736  float height;
3737  int columns;
3738  const float *ratio;
3739  float item_width;
3742  float filled;
3743  struct nk_rect item;
3746 };
3747 
3749  nk_size begin;
3750  nk_size parent;
3751  nk_size last;
3752  nk_size end;
3753  int active;
3754 };
3755 
3757  float x, y, w, h;
3759 };
3760 
3761 struct nk_panel {
3763  nk_flags flags;
3764  struct nk_rect bounds;
3765  nk_uint *offset_x;
3766  nk_uint *offset_y;
3767  float at_x, at_y, max_x;
3770  float border;
3771  unsigned int has_scrolling;
3772  struct nk_rect clip;
3775  struct nk_chart chart;
3777  struct nk_panel *parent;
3778 };
3779 
3780 /*==============================================================
3781  * WINDOW
3782  * =============================================================*/
3783 #ifndef NK_WINDOW_MAX_NAME
3784 #define NK_WINDOW_MAX_NAME 64
3785 #endif
3786 
3787 struct nk_table;
3791  /* special window type growing up in height while being filled to a certain maximum height */
3793  /* sets window widgets into a read only mode and does not allow input changes */
3795  /* prevents all interaction caused by input to either window or widgets inside */
3797  /* Hides window and stops any window interaction and drawing */
3799  /* Directly closes and frees the window at the end of the frame */
3801  /* marks the window as minimized */
3803  /* Removes read only mode at the end of the window */
3804 };
3805 
3807  struct nk_window *win;
3810  nk_hash name;
3811  int active;
3812  unsigned combo_count;
3813  unsigned con_count, con_old;
3814  unsigned active_con;
3815  struct nk_rect header;
3816 };
3817 
3819  nk_hash name;
3820  unsigned int seq;
3821  unsigned int old;
3822  int active, prev;
3823  int cursor;
3825  int sel_end;
3827  unsigned char mode;
3828  unsigned char single_line;
3829 };
3830 
3832  int active, prev;
3834  int length;
3835  int cursor;
3838  nk_hash name;
3839  unsigned int seq;
3840  unsigned int old;
3841  int state;
3842 };
3843 
3844 struct nk_window {
3845  unsigned int seq;
3846  nk_hash name;
3848  nk_flags flags;
3849 
3850  struct nk_rect bounds;
3853  struct nk_panel *layout;
3855 
3856  /* persistent widget state */
3860  unsigned int scrolled;
3861 
3862  struct nk_table *tables;
3863  unsigned short table_count;
3864  unsigned short table_size;
3865 
3866  /* window list hooks */
3867  struct nk_window *next;
3868  struct nk_window *prev;
3870 };
3871 
3872 /*==============================================================
3873  * STACK
3874  * =============================================================*/
3875 /* The style modifier stack can be used to temporarily change a
3876  * property inside `nk_style`. For example if you want a special
3877  * red button you can temporarily push the old button color onto a stack
3878  * draw the button with a red color and then you just pop the old color
3879  * back from the stack:
3880  *
3881  * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
3882  * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
3883  * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
3884  * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
3885  *
3886  * nk_button(...);
3887  *
3888  * nk_style_pop_style_item(ctx);
3889  * nk_style_pop_style_item(ctx);
3890  * nk_style_pop_style_item(ctx);
3891  * nk_style_pop_vec2(ctx);
3892  *
3893  * Nuklear has a stack for style_items, float properties, vector properties,
3894  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
3895  * which can be changed at compile time.
3896  */
3897 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
3898 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
3899 #endif
3900 
3901 #ifndef NK_FONT_STACK_SIZE
3902 #define NK_FONT_STACK_SIZE 8
3903 #endif
3904 
3905 #ifndef NK_STYLE_ITEM_STACK_SIZE
3906 #define NK_STYLE_ITEM_STACK_SIZE 16
3907 #endif
3908 
3909 #ifndef NK_FLOAT_STACK_SIZE
3910 #define NK_FLOAT_STACK_SIZE 32
3911 #endif
3912 
3913 #ifndef NK_VECTOR_STACK_SIZE
3914 #define NK_VECTOR_STACK_SIZE 16
3915 #endif
3916 
3917 #ifndef NK_FLAGS_STACK_SIZE
3918 #define NK_FLAGS_STACK_SIZE 32
3919 #endif
3920 
3921 #ifndef NK_COLOR_STACK_SIZE
3922 #define NK_COLOR_STACK_SIZE 32
3923 #endif
3924 
3925 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
3926  struct nk_config_stack_##name##_element {\
3927  prefix##_##type *address;\
3928  prefix##_##type old_value;\
3929  }
3930 #define NK_CONFIG_STACK(type,size)\
3931  struct nk_config_stack_##type {\
3932  int head;\
3933  struct nk_config_stack_##type##_element elements[size];\
3934  }
3935 
3936 #define nk_float float
3937 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
3938 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
3939 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
3941 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
3942 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
3943 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
3944 
3952 
3954  struct nk_config_stack_style_item style_items;
3955  struct nk_config_stack_float floats;
3956  struct nk_config_stack_vec2 vectors;
3957  struct nk_config_stack_flags flags;
3958  struct nk_config_stack_color colors;
3959  struct nk_config_stack_user_font fonts;
3960  struct nk_config_stack_button_behavior button_behaviors;
3961 };
3962 
3963 /*==============================================================
3964  * CONTEXT
3965  * =============================================================*/
3966 #define NK_VALUE_PAGE_CAPACITY \
3967  ((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint)) / 2)
3968 
3969 struct nk_table {
3970  unsigned int seq;
3973  struct nk_table *next, *prev;
3974 };
3975 
3977  struct nk_table tbl;
3978  struct nk_panel pan;
3979  struct nk_window win;
3980 };
3981 
3986 };
3987 
3988 struct nk_page {
3989  unsigned int size;
3990  struct nk_page *next;
3992 };
3993 
3994 struct nk_pool {
3997  unsigned int page_count;
3998  struct nk_page *pages;
4000  unsigned capacity;
4001  nk_size size;
4002  nk_size cap;
4003 };
4004 
4005 struct nk_context {
4006 /* public: can be accessed freely */
4007  struct nk_input input;
4008  struct nk_style style;
4015 
4016 /* private:
4017  should only be accessed if you
4018  know what you are doing */
4019 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4020  struct nk_draw_list draw_list;
4021 #endif
4022 #ifdef NK_INCLUDE_COMMAND_USERDATA
4023  nk_handle userdata;
4024 #endif
4025  /* text editor objects are quite big because of an internal
4026  * undo/redo stack. Therefore it does not make sense to have one for
4027  * each window for temporary use cases, so I only provide *one* instance
4028  * for all windows. This works because the content is cleared anyway */
4030  /* draw buffer used for overlay drawing operation like cursor */
4032 
4033  /* windows */
4034  int build;
4036  struct nk_pool pool;
4037  struct nk_window *begin;
4038  struct nk_window *end;
4042  unsigned int count;
4043  unsigned int seq;
4044 };
4045 
4046 /* ==============================================================
4047  * MATH
4048  * =============================================================== */
4049 #define NK_PI 3.141592654f
4050 #define NK_UTF_INVALID 0xFFFD
4051 #define NK_MAX_FLOAT_PRECISION 2
4052 
4053 #define NK_UNUSED(x) ((void)(x))
4054 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
4055 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
4056 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
4057 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
4058 #define NK_INBOX(px, py, x, y, w, h)\
4059  (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
4060 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
4061  (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
4062 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
4063  (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
4064 
4065 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
4066 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
4067 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
4068 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
4069 
4070 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
4071 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
4072 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
4073 
4074 /* ==============================================================
4075  * ALIGNMENT
4076  * =============================================================== */
4077 /* Pointer to Integer type conversion for pointer alignment */
4078 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
4079 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
4080 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
4081 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
4082 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
4083 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
4084 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
4085 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
4086 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
4087 #else /* generates warning but works */
4088 # define NK_UINT_TO_PTR(x) ((void*)(x))
4089 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
4090 #endif
4091 
4092 #define NK_ALIGN_PTR(x, mask)\
4093  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
4094 #define NK_ALIGN_PTR_BACK(x, mask)\
4095  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
4096 
4097 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
4098 #define NK_CONTAINER_OF(ptr,type,member)\
4099  (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
4100 
4101 #ifdef __cplusplus
4102 }
4103 #endif
4104 
4105 #ifdef __cplusplus
4106 template<typename T> struct nk_alignof;
4107 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
4108 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
4109 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
4110  diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
4111 #define NK_ALIGNOF(t) (nk_alignof<t>::value);
4112 #elif defined(_MSC_VER)
4113 #define NK_ALIGNOF(t) (__alignof(t))
4114 #else
4115 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
4116 #endif
4117 
4118 #endif /* NK_H_ */
4119 /*
4120  * ==============================================================
4121  *
4122  * IMPLEMENTATION
4123  *
4124  * ===============================================================
4125  */
4126 #ifdef NK_IMPLEMENTATION
4127 
4128 #ifndef NK_POOL_DEFAULT_CAPACITY
4129 #define NK_POOL_DEFAULT_CAPACITY 16
4130 #endif
4131 
4132 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
4133 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
4134 #endif
4135 
4136 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
4137 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
4138 #endif
4139 
4140 /* standard library headers */
4141 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4142 #include <stdlib.h> /* malloc, free */
4143 #endif
4144 #ifdef NK_INCLUDE_STANDARD_IO
4145 #include <stdio.h> /* fopen, fclose,... */
4146 #endif
4147 #ifdef NK_INCLUDE_STANDARD_VARARGS
4148 #include <stdarg.h> /* valist, va_start, va_end, ... */
4149 #endif
4150 #ifndef NK_ASSERT
4151 #include <assert.h>
4152 #define NK_ASSERT(expr) assert(expr)
4153 #endif
4154 
4155 #ifndef NK_MEMSET
4156 #define NK_MEMSET nk_memset
4157 #endif
4158 #ifndef NK_MEMCPY
4159 #define NK_MEMCPY nk_memcopy
4160 #endif
4161 #ifndef NK_SQRT
4162 #define NK_SQRT nk_sqrt
4163 #endif
4164 #ifndef NK_SIN
4165 #define NK_SIN nk_sin
4166 #endif
4167 #ifndef NK_COS
4168 #define NK_COS nk_cos
4169 #endif
4170 #ifndef NK_STRTOD
4171 #define NK_STRTOD nk_strtod
4172 #endif
4173 #ifndef NK_DTOA
4174 #define NK_DTOA nk_dtoa
4175 #endif
4176 
4177 #define NK_DEFAULT (-1)
4178 
4179 #ifndef NK_VSNPRINTF
4180 /* If your compiler does support `vsnprintf` I would highly recommend
4181  * defining this to vsnprintf instead since `vsprintf` is basically
4182  * unbelievable unsafe and should *NEVER* be used. But I have to support
4183  * it since C89 only provides this unsafe version. */
4184  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
4185  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
4186  (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
4187  (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
4188  defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
4189  #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
4190  #else
4191  #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
4192  #endif
4193 #endif
4194 
4195 #define NK_SCHAR_MIN (-127)
4196 #define NK_SCHAR_MAX 127
4197 #define NK_UCHAR_MIN 0
4198 #define NK_UCHAR_MAX 256
4199 #define NK_SSHORT_MIN (-32767)
4200 #define NK_SSHORT_MAX 32767
4201 #define NK_USHORT_MIN 0
4202 #define NK_USHORT_MAX 65535
4203 #define NK_SINT_MIN (-2147483647)
4204 #define NK_SINT_MAX 2147483647
4205 #define NK_UINT_MIN 0
4206 #define NK_UINT_MAX 4294967295u
4207 
4208 /* Make sure correct type size:
4209  * This will fire with a negative subscript error if the type sizes
4210  * are set incorrectly by the compiler, and compile out if not */
4211 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
4212 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
4213 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
4214 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
4215 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
4216 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
4217 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
4218 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
4219 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
4220 
4221 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
4222 #define NK_FLOAT_PRECISION 0.00000000000001
4223 
4224 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
4225 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
4226 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
4227 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
4228 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
4229 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
4230 
4231 /*
4232  * ==============================================================
4233  *
4234  * MATH
4235  *
4236  * ===============================================================
4237  */
4238 /* Since nuklear is supposed to work on all systems providing floating point
4239  math without any dependencies I also had to implement my own math functions
4240  for sqrt, sin and cos. Since the actual highly accurate implementations for
4241  the standard library functions are quite complex and I do not need high
4242  precision for my use cases I use approximations.
4243 
4244  Sqrt
4245  ----
4246  For square root nuklear uses the famous fast inverse square root:
4247  https://en.wikipedia.org/wiki/Fast_inverse_square_root with
4248  slightly tweaked magic constant. While on todays hardware it is
4249  probably not faster it is still fast and accurate enough for
4250  nuklear's use cases. IMPORTANT: this requires float format IEEE 754
4251 
4252  Sine/Cosine
4253  -----------
4254  All constants inside both function are generated Remez's minimax
4255  approximations for value range 0...2*PI. The reason why I decided to
4256  approximate exactly that range is that nuklear only needs sine and
4257  cosine to generate circles which only requires that exact range.
4258  In addition I used Remez instead of Taylor for additional precision:
4259  www.lolengine.net/blog/2011/12/21/better-function-approximatations.
4260 
4261  The tool I used to generate constants for both sine and cosine
4262  (it can actually approximate a lot more functions) can be
4263  found here: www.lolengine.net/wiki/oss/lolremez
4264 */
4265 NK_INTERN float
4266 nk_inv_sqrt(float number)
4267 {
4268  float x2;
4269  const float threehalfs = 1.5f;
4270  union {nk_uint i; float f;} conv = {0};
4271  conv.f = number;
4272  x2 = number * 0.5f;
4273  conv.i = 0x5f375A84 - (conv.i >> 1);
4274  conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
4275  return conv.f;
4276 }
4277 
4278 NK_INTERN float
4279 nk_sqrt(float x)
4280 {
4281  return x * nk_inv_sqrt(x);
4282 }
4283 
4284 NK_INTERN float
4285 nk_sin(float x)
4286 {
4287  NK_STORAGE const float a0 = +1.91059300966915117e-31f;
4288  NK_STORAGE const float a1 = +1.00086760103908896f;
4289  NK_STORAGE const float a2 = -1.21276126894734565e-2f;
4290  NK_STORAGE const float a3 = -1.38078780785773762e-1f;
4291  NK_STORAGE const float a4 = -2.67353392911981221e-2f;
4292  NK_STORAGE const float a5 = +2.08026600266304389e-2f;
4293  NK_STORAGE const float a6 = -3.03996055049204407e-3f;
4294  NK_STORAGE const float a7 = +1.38235642404333740e-4f;
4295  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4296 }
4297 
4298 NK_INTERN float
4299 nk_cos(float x)
4300 {
4301  NK_STORAGE const float a0 = +1.00238601909309722f;
4302  NK_STORAGE const float a1 = -3.81919947353040024e-2f;
4303  NK_STORAGE const float a2 = -3.94382342128062756e-1f;
4304  NK_STORAGE const float a3 = -1.18134036025221444e-1f;
4305  NK_STORAGE const float a4 = +1.07123798512170878e-1f;
4306  NK_STORAGE const float a5 = -1.86637164165180873e-2f;
4307  NK_STORAGE const float a6 = +9.90140908664079833e-4f;
4308  NK_STORAGE const float a7 = -5.23022132118824778e-14f;
4309  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4310 }
4311 
4312 NK_INTERN nk_uint
4313 nk_round_up_pow2(nk_uint v)
4314 {
4315  v--;
4316  v |= v >> 1;
4317  v |= v >> 2;
4318  v |= v >> 4;
4319  v |= v >> 8;
4320  v |= v >> 16;
4321  v++;
4322  return v;
4323 }
4324 
4325 NK_API struct nk_rect
4327 {
4328  return nk_null_rect;
4329 }
4330 
4331 NK_API struct nk_rect
4332 nk_rect(float x, float y, float w, float h)
4333 {
4334  struct nk_rect r;
4335  r.x = x; r.y = y;
4336  r.w = w; r.h = h;
4337  return r;
4338 }
4339 
4340 NK_API struct nk_rect
4341 nk_recti(int x, int y, int w, int h)
4342 {
4343  struct nk_rect r;
4344  r.x = (float)x;
4345  r.y = (float)y;
4346  r.w = (float)w;
4347  r.h = (float)h;
4348  return r;
4349 }
4350 
4351 NK_API struct nk_rect
4352 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
4353 {
4354  return nk_rect(pos.x, pos.y, size.x, size.y);
4355 }
4356 
4357 NK_API struct nk_rect
4358 nk_rectv(const float *r)
4359 {
4360  return nk_rect(r[0], r[1], r[2], r[3]);
4361 }
4362 
4363 NK_API struct nk_rect
4364 nk_rectiv(const int *r)
4365 {
4366  return nk_recti(r[0], r[1], r[2], r[3]);
4367 }
4368 
4369 NK_API struct nk_vec2
4370 nk_rect_pos(struct nk_rect r)
4371 {
4372  struct nk_vec2 ret;
4373  ret.x = r.x; ret.y = r.y;
4374  return ret;
4375 }
4376 
4377 NK_API struct nk_vec2
4378 nk_rect_size(struct nk_rect r)
4379 {
4380  struct nk_vec2 ret;
4381  ret.x = r.w; ret.y = r.h;
4382  return ret;
4383 }
4384 
4385 NK_INTERN struct nk_rect
4386 nk_shrink_rect(struct nk_rect r, float amount)
4387 {
4388  struct nk_rect res;
4389  r.w = NK_MAX(r.w, 2 * amount);
4390  r.h = NK_MAX(r.h, 2 * amount);
4391  res.x = r.x + amount;
4392  res.y = r.y + amount;
4393  res.w = r.w - 2 * amount;
4394  res.h = r.h - 2 * amount;
4395  return res;
4396 }
4397 
4398 NK_INTERN struct nk_rect
4399 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
4400 {
4401  r.w = NK_MAX(r.w, 2 * pad.x);
4402  r.h = NK_MAX(r.h, 2 * pad.y);
4403  r.x += pad.x; r.y += pad.y;
4404  r.w -= 2 * pad.x;
4405  r.h -= 2 * pad.y;
4406  return r;
4407 }
4408 
4409 NK_API struct nk_vec2
4410 nk_vec2(float x, float y)
4411 {
4412  struct nk_vec2 ret;
4413  ret.x = x; ret.y = y;
4414  return ret;
4415 }
4416 
4417 NK_API struct nk_vec2
4418 nk_vec2i(int x, int y)
4419 {
4420  struct nk_vec2 ret;
4421  ret.x = (float)x;
4422  ret.y = (float)y;
4423  return ret;
4424 }
4425 
4426 NK_API struct nk_vec2
4427 nk_vec2v(const float *v)
4428 {
4429  return nk_vec2(v[0], v[1]);
4430 }
4431 
4432 NK_API struct nk_vec2
4433 nk_vec2iv(const int *v)
4434 {
4435  return nk_vec2i(v[0], v[1]);
4436 }
4437 
4438 /*
4439  * ==============================================================
4440  *
4441  * UTIL
4442  *
4443  * ===============================================================
4444  */
4445 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
4446 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
4447 NK_INTERN int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
4448 NK_INTERN int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
4449 NK_INTERN int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
4450 NK_INTERN int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
4451 
4452 NK_INTERN void*
4453 nk_memcopy(void *dst0, const void *src0, nk_size length)
4454 {
4455  nk_ptr t;
4456  char *dst = (char*)dst0;
4457  const char *src = (const char*)src0;
4458  if (length == 0 || dst == src)
4459  goto done;
4460 
4461  #define nk_word int
4462  #define nk_wsize sizeof(nk_word)
4463  #define nk_wmask (nk_wsize-1)
4464  #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
4465  #define NK_TLOOP1(s) do { s; } while (--t)
4466 
4467  if (dst < src) {
4468  t = (nk_ptr)src; /* only need low bits */
4469  if ((t | (nk_ptr)dst) & nk_wmask) {
4470  if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
4471  t = length;
4472  else
4473  t = nk_wsize - (t & nk_wmask);
4474  length -= t;
4475  NK_TLOOP1(*dst++ = *src++);
4476  }
4477  t = length / nk_wsize;
4478  NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
4479  src += nk_wsize; dst += nk_wsize);
4480  t = length & nk_wmask;
4481  NK_TLOOP(*dst++ = *src++);
4482  } else {
4483  src += length;
4484  dst += length;
4485  t = (nk_ptr)src;
4486  if ((t | (nk_ptr)dst) & nk_wmask) {
4487  if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
4488  t = length;
4489  else
4490  t &= nk_wmask;
4491  length -= t;
4492  NK_TLOOP1(*--dst = *--src);
4493  }
4494  t = length / nk_wsize;
4495  NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
4496  *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
4497  t = length & nk_wmask;
4498  NK_TLOOP(*--dst = *--src);
4499  }
4500  #undef nk_word
4501  #undef nk_wsize
4502  #undef nk_wmask
4503  #undef NK_TLOOP
4504  #undef NK_TLOOP1
4505 done:
4506  return (dst0);
4507 }
4508 
4509 NK_INTERN void
4510 nk_memset(void *ptr, int c0, nk_size size)
4511 {
4512  #define nk_word unsigned
4513  #define nk_wsize sizeof(nk_word)
4514  #define nk_wmask (nk_wsize - 1)
4515  nk_byte *dst = (nk_byte*)ptr;
4516  unsigned c = 0;
4517  nk_size t = 0;
4518 
4519  if ((c = (nk_byte)c0) != 0) {
4520  c = (c << 8) | c; /* at least 16-bits */
4521  if (sizeof(unsigned int) > 2)
4522  c = (c << 16) | c; /* at least 32-bits*/
4523  }
4524 
4525  /* too small of a word count */
4526  dst = (nk_byte*)ptr;
4527  if (size < 3 * nk_wsize) {
4528  while (size--) *dst++ = (nk_byte)c0;
4529  return;
4530  }
4531 
4532  /* align destination */
4533  if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
4534  t = nk_wsize -t;
4535  size -= t;
4536  do {
4537  *dst++ = (nk_byte)c0;
4538  } while (--t != 0);
4539  }
4540 
4541  /* fill word */
4542  t = size / nk_wsize;
4543  do {
4544  *(nk_word*)((void*)dst) = c;
4545  dst += nk_wsize;
4546  } while (--t != 0);
4547 
4548  /* fill trailing bytes */
4549  t = (size & nk_wmask);
4550  if (t != 0) {
4551  do {
4552  *dst++ = (nk_byte)c0;
4553  } while (--t != 0);
4554  }
4555 
4556  #undef nk_word
4557  #undef nk_wsize
4558  #undef nk_wmask
4559 }
4560 
4561 NK_INTERN void
4562 nk_zero(void *ptr, nk_size size)
4563 {
4564  NK_ASSERT(ptr);
4565  NK_MEMSET(ptr, 0, size);
4566 }
4567 
4568 NK_API int
4569 nk_strlen(const char *str)
4570 {
4571  int siz = 0;
4572  NK_ASSERT(str);
4573  while (str && *str++ != '\0') siz++;
4574  return siz;
4575 }
4576 
4577 NK_API int
4578 nk_strtoi(const char *str, const char **endptr)
4579 {
4580  int neg = 1;
4581  const char *p = str;
4582  int value = 0;
4583 
4584  NK_ASSERT(str);
4585  if (!str) return 0;
4586 
4587  /* skip whitespace */
4588  while (*p == ' ') p++;
4589  if (*p == '-') {
4590  neg = -1;
4591  p++;
4592  }
4593  while (*p && *p >= '0' && *p <= '9') {
4594  value = value * 10 + (int) (*p - '0');
4595  p++;
4596  }
4597  if (endptr)
4598  *endptr = p;
4599  return neg*value;
4600 }
4601 
4602 NK_API double
4603 nk_strtod(const char *str, const char **endptr)
4604 {
4605  double m;
4606  double neg = 1.0;
4607  const char *p = str;
4608  double value = 0;
4609  double number = 0;
4610 
4611  NK_ASSERT(str);
4612  if (!str) return 0;
4613 
4614  /* skip whitespace */
4615  while (*p == ' ') p++;
4616  if (*p == '-') {
4617  neg = -1.0;
4618  p++;
4619  }
4620 
4621  while (*p && *p != '.' && *p != 'e') {
4622  value = value * 10.0 + (double) (*p - '0');
4623  p++;
4624  }
4625 
4626  if (*p == '.') {
4627  p++;
4628  for(m = 0.1; *p && *p != 'e'; p++ ) {
4629  value = value + (double) (*p - '0') * m;
4630  m *= 0.1;
4631  }
4632  }
4633  if (*p == 'e') {
4634  int i, pow, div;
4635  p++;
4636  if (*p == '-') {
4637  div = nk_true;
4638  p++;
4639  } else if (*p == '+') {
4640  div = nk_false;
4641  p++;
4642  } else div = nk_false;
4643 
4644  for (pow = 0; *p; p++)
4645  pow = pow * 10 + (int) (*p - '0');
4646 
4647  for (m = 1.0, i = 0; i < pow; i++)
4648  m *= 10.0;
4649 
4650  if (div)
4651  value /= m;
4652  else value *= m;
4653  }
4654  number = value * neg;
4655  if (endptr)
4656  *endptr = p;
4657  return number;
4658 }
4659 
4660 NK_API float
4661 nk_strtof(const char *str, const char **endptr)
4662 {
4663  float float_value;
4664  double double_value;
4665  double_value = NK_STRTOD(str, endptr);
4666  float_value = (float)double_value;
4667  return float_value;
4668 }
4669 
4670 NK_API int
4671 nk_stricmp(const char *s1, const char *s2)
4672 {
4673  nk_int c1,c2,d;
4674  do {
4675  c1 = *s1++;
4676  c2 = *s2++;
4677  d = c1 - c2;
4678  while (d) {
4679  if (c1 <= 'Z' && c1 >= 'A') {
4680  d += ('a' - 'A');
4681  if (!d) break;
4682  }
4683  if (c2 <= 'Z' && c2 >= 'A') {
4684  d -= ('a' - 'A');
4685  if (!d) break;
4686  }
4687  return ((d >= 0) << 1) - 1;
4688  }
4689  } while (c1);
4690  return 0;
4691 }
4692 
4693 NK_API int
4694 nk_stricmpn(const char *s1, const char *s2, int n)
4695 {
4696  int c1,c2,d;
4697  NK_ASSERT(n >= 0);
4698  do {
4699  c1 = *s1++;
4700  c2 = *s2++;
4701  if (!n--) return 0;
4702 
4703  d = c1 - c2;
4704  while (d) {
4705  if (c1 <= 'Z' && c1 >= 'A') {
4706  d += ('a' - 'A');
4707  if (!d) break;
4708  }
4709  if (c2 <= 'Z' && c2 >= 'A') {
4710  d -= ('a' - 'A');
4711  if (!d) break;
4712  }
4713  return ((d >= 0) << 1) - 1;
4714  }
4715  } while (c1);
4716  return 0;
4717 }
4718 
4719 NK_INTERN int
4720 nk_str_match_here(const char *regexp, const char *text)
4721 {
4722  if (regexp[0] == '\0')
4723  return 1;
4724  if (regexp[1] == '*')
4725  return nk_str_match_star(regexp[0], regexp+2, text);
4726  if (regexp[0] == '$' && regexp[1] == '\0')
4727  return *text == '\0';
4728  if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
4729  return nk_str_match_here(regexp+1, text+1);
4730  return 0;
4731 }
4732 
4733 NK_INTERN int
4734 nk_str_match_star(int c, const char *regexp, const char *text)
4735 {
4736  do {/* a '* matches zero or more instances */
4737  if (nk_str_match_here(regexp, text))
4738  return 1;
4739  } while (*text != '\0' && (*text++ == c || c == '.'));
4740  return 0;
4741 }
4742 
4743 NK_API int
4744 nk_strfilter(const char *text, const char *regexp)
4745 {
4746  /*
4747  c matches any literal character c
4748  . matches any single character
4749  ^ matches the beginning of the input string
4750  $ matches the end of the input string
4751  * matches zero or more occurrences of the previous character*/
4752  if (regexp[0] == '^')
4753  return nk_str_match_here(regexp+1, text);
4754  do { /* must look even if string is empty */
4755  if (nk_str_match_here(regexp, text))
4756  return 1;
4757  } while (*text++ != '\0');
4758  return 0;
4759 }
4760 
4761 NK_API int
4762 nk_strmatch_fuzzy_text(const char *str, int str_len,
4763  const char *pattern, int *out_score)
4764 {
4765  /* Returns true if each character in pattern is found sequentially within str
4766  * if found then outScore is also set. Score value has no intrinsic meaning.
4767  * Range varies with pattern. Can only compare scores with same search pattern. */
4768 
4769  /* ------- scores --------- */
4770  /* bonus for adjacent matches */
4771  #define NK_ADJACENCY_BONUS 5
4772  /* bonus if match occurs after a separator */
4773  #define NK_SEPARATOR_BONUS 10
4774  /* bonus if match is uppercase and prev is lower */
4775  #define NK_CAMEL_BONUS 10
4776  /* penalty applied for every letter in str before the first match */
4777  #define NK_LEADING_LETTER_PENALTY (-3)
4778  /* maximum penalty for leading letters */
4779  #define NK_MAX_LEADING_LETTER_PENALTY (-9)
4780  /* penalty for every letter that doesn't matter */
4781  #define NK_UNMATCHED_LETTER_PENALTY (-1)
4782 
4783  /* loop variables */
4784  int score = 0;
4785  char const * pattern_iter = pattern;
4786  int str_iter = 0;
4787  int prev_matched = nk_false;
4788  int prev_lower = nk_false;
4789  /* true so if first letter match gets separator bonus*/
4790  int prev_separator = nk_true;
4791 
4792  /* use "best" matched letter if multiple string letters match the pattern */
4793  char const * best_letter = 0;
4794  int best_letter_score = 0;
4795 
4796  /* loop over strings */
4797  NK_ASSERT(str);
4798  NK_ASSERT(pattern);
4799  if (!str || !str_len || !pattern) return 0;
4800  while (str_iter < str_len)
4801  {
4802  const char pattern_letter = *pattern_iter;
4803  const char str_letter = str[str_iter];
4804 
4805  int next_match = *pattern_iter != '\0' &&
4806  nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
4807  int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
4808 
4809  int advanced = next_match && best_letter;
4810  int pattern_repeat = best_letter && *pattern_iter != '\0';
4811  pattern_repeat = pattern_repeat &&
4812  nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
4813 
4814  if (advanced || pattern_repeat) {
4815  score += best_letter_score;
4816  best_letter = 0;
4817  best_letter_score = 0;
4818  }
4819 
4820  if (next_match || rematch)
4821  {
4822  int new_score = 0;
4823  /* Apply penalty for each letter before the first pattern match */
4824  if (pattern_iter == pattern) {
4825  int count = (int)(&str[str_iter] - str);
4826  int penalty = NK_LEADING_LETTER_PENALTY * count;
4827  if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
4828  penalty = NK_MAX_LEADING_LETTER_PENALTY;
4829 
4830  score += penalty;
4831  }
4832 
4833  /* apply bonus for consecutive bonuses */
4834  if (prev_matched)
4835  new_score += NK_ADJACENCY_BONUS;
4836 
4837  /* apply bonus for matches after a separator */
4838  if (prev_separator)
4839  new_score += NK_SEPARATOR_BONUS;
4840 
4841  /* apply bonus across camel case boundaries */
4842  if (prev_lower && nk_is_upper(str_letter))
4843  new_score += NK_CAMEL_BONUS;
4844 
4845  /* update pattern iter IFF the next pattern letter was matched */
4846  if (next_match)
4847  ++pattern_iter;
4848 
4849  /* update best letter in str which may be for a "next" letter or a rematch */
4850  if (new_score >= best_letter_score) {
4851  /* apply penalty for now skipped letter */
4852  if (best_letter != 0)
4853  score += NK_UNMATCHED_LETTER_PENALTY;
4854 
4855  best_letter = &str[str_iter];
4856  best_letter_score = new_score;
4857  }
4858  prev_matched = nk_true;
4859  } else {
4860  score += NK_UNMATCHED_LETTER_PENALTY;
4861  prev_matched = nk_false;
4862  }
4863 
4864  /* separators should be more easily defined */
4865  prev_lower = nk_is_lower(str_letter) != 0;
4866  prev_separator = str_letter == '_' || str_letter == ' ';
4867 
4868  ++str_iter;
4869  }
4870 
4871  /* apply score for last match */
4872  if (best_letter)
4873  score += best_letter_score;
4874 
4875  /* did not match full pattern */
4876  if (*pattern_iter != '\0')
4877  return nk_false;
4878 
4879  if (out_score)
4880  *out_score = score;
4881  return nk_true;
4882 }
4883 
4884 NK_API int
4885 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
4886 {return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);}
4887 
4888 NK_INTERN int
4889 nk_string_float_limit(char *string, int prec)
4890 {
4891  int dot = 0;
4892  char *c = string;
4893  while (*c) {
4894  if (*c == '.') {
4895  dot = 1;
4896  c++;
4897  continue;
4898  }
4899  if (dot == (prec+1)) {
4900  *c = 0;
4901  break;
4902  }
4903  if (dot > 0) dot++;
4904  c++;
4905  }
4906  return (int)(c - string);
4907 }
4908 
4909 NK_INTERN double
4910 nk_pow(double x, int n)
4911 {
4912  /* check the sign of n */
4913  double r = 1;
4914  int plus = n >= 0;
4915  n = (plus) ? n : -n;
4916  while (n > 0) {
4917  if ((n & 1) == 1)
4918  r *= x;
4919  n /= 2;
4920  x *= x;
4921  }
4922  return plus ? r : 1.0 / r;
4923 }
4924 
4925 NK_INTERN int
4926 nk_ifloord(double x)
4927 {
4928  x = (double)((int)x - ((x < 0.0) ? 1 : 0));
4929  return (int)x;
4930 }
4931 
4932 NK_INTERN int
4933 nk_ifloorf(float x)
4934 {
4935  x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
4936  return (int)x;
4937 }
4938 
4939 NK_INTERN int
4940 nk_iceilf(float x)
4941 {
4942  if (x >= 0) {
4943  int i = (int)x;
4944  return i;
4945  } else {
4946  int t = (int)x;
4947  float r = x - (float)t;
4948  return (r > 0.0f) ? t+1: t;
4949  }
4950 }
4951 
4952 NK_INTERN int
4953 nk_log10(double n)
4954 {
4955  int neg;
4956  int ret;
4957  int exp = 0;
4958 
4959  neg = (n < 0) ? 1 : 0;
4960  ret = (neg) ? (int)-n : (int)n;
4961  while ((ret / 10) > 0) {
4962  ret /= 10;
4963  exp++;
4964  }
4965  if (neg) exp = -exp;
4966  return exp;
4967 }
4968 
4969 NK_INTERN void
4970 nk_strrev_ascii(char *s)
4971 {
4972  int len = nk_strlen(s);
4973  int end = len / 2;
4974  int i = 0;
4975  char t;
4976  for (; i < end; ++i) {
4977  t = s[i];
4978  s[i] = s[len - 1 - i];
4979  s[len -1 - i] = t;
4980  }
4981 }
4982 
4983 NK_INTERN char*
4984 nk_itoa(char *s, long n)
4985 {
4986  long i = 0;
4987  if (n == 0) {
4988  s[i++] = '0';
4989  s[i] = 0;
4990  return s;
4991  }
4992  if (n < 0) {
4993  s[i++] = '-';
4994  n = -n;
4995  }
4996  while (n > 0) {
4997  s[i++] = (char)('0' + (n % 10));
4998  n /= 10;
4999  }
5000  s[i] = 0;
5001  if (s[0] == '-')
5002  ++s;
5003 
5004  nk_strrev_ascii(s);
5005  return s;
5006 }
5007 
5008 NK_INTERN char*
5009 nk_dtoa(char *s, double n)
5010 {
5011  int useExp = 0;
5012  int digit = 0, m = 0, m1 = 0;
5013  char *c = s;
5014  int neg = 0;
5015 
5016  NK_ASSERT(s);
5017  if (!s) return 0;
5018 
5019  if (n == 0.0) {
5020  s[0] = '0'; s[1] = '\0';
5021  return s;
5022  }
5023 
5024  neg = (n < 0);
5025  if (neg) n = -n;
5026 
5027  /* calculate magnitude */
5028  m = nk_log10(n);
5029  useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
5030  if (neg) *(c++) = '-';
5031 
5032  /* set up for scientific notation */
5033  if (useExp) {
5034  if (m < 0)
5035  m -= 1;
5036  n = n / (double)nk_pow(10.0, m);
5037  m1 = m;
5038  m = 0;
5039  }
5040  if (m < 1.0) {
5041  m = 0;
5042  }
5043 
5044  /* convert the number */
5045  while (n > NK_FLOAT_PRECISION || m >= 0) {
5046  double weight = nk_pow(10.0, m);
5047  if (weight > 0) {
5048  double t = (double)n / weight;
5049  digit = nk_ifloord(t);
5050  n -= ((double)digit * weight);
5051  *(c++) = (char)('0' + (char)digit);
5052  }
5053  if (m == 0 && n > 0)
5054  *(c++) = '.';
5055  m--;
5056  }
5057 
5058  if (useExp) {
5059  /* convert the exponent */
5060  int i, j;
5061  *(c++) = 'e';
5062  if (m1 > 0) {
5063  *(c++) = '+';
5064  } else {
5065  *(c++) = '-';
5066  m1 = -m1;
5067  }
5068  m = 0;
5069  while (m1 > 0) {
5070  *(c++) = (char)('0' + (char)(m1 % 10));
5071  m1 /= 10;
5072  m++;
5073  }
5074  c -= m;
5075  for (i = 0, j = m-1; i<j; i++, j--) {
5076  /* swap without temporary */
5077  c[i] ^= c[j];
5078  c[j] ^= c[i];
5079  c[i] ^= c[j];
5080  }
5081  c += m;
5082  }
5083  *(c) = '\0';
5084  return s;
5085 }
5086 
5087 #ifdef NK_INCLUDE_STANDARD_VARARGS
5088 #ifndef NK_INCLUDE_STANDARD_IO
5089 static int
5090 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
5091 {
5092  enum nk_arg_type {
5093  NK_ARG_TYPE_CHAR,
5094  NK_ARG_TYPE_SHORT,
5095  NK_ARG_TYPE_DEFAULT,
5096  NK_ARG_TYPE_LONG
5097  };
5098  enum nk_arg_flags {
5099  NK_ARG_FLAG_LEFT = 0x01,
5100  NK_ARG_FLAG_PLUS = 0x02,
5101  NK_ARG_FLAG_SPACE = 0x04,
5102  NK_ARG_FLAG_NUM = 0x10,
5103  NK_ARG_FLAG_ZERO = 0x20
5104  };
5105 
5106  char number_buffer[NK_MAX_NUMBER_BUFFER];
5107  enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
5108  int precision = NK_DEFAULT;
5109  int width = NK_DEFAULT;
5110  nk_flags flag = 0;
5111 
5112  int len = 0;
5113  int result = -1;
5114  const char *iter = fmt;
5115 
5116  NK_ASSERT(buf);
5117  NK_ASSERT(buf_size);
5118  if (!buf || !buf_size || !fmt) return 0;
5119  for (iter = fmt; *iter && len < buf_size; iter++) {
5120  /* copy all non-format characters */
5121  while (*iter && (*iter != '%') && (len < buf_size))
5122  buf[len++] = *iter++;
5123  if (!(*iter) || len >= buf_size) break;
5124  iter++;
5125 
5126  /* flag arguments */
5127  while (*iter) {
5128  if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
5129  else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
5130  else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
5131  else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
5132  else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
5133  else break;
5134  iter++;
5135  }
5136 
5137  /* width argument */
5138  width = NK_DEFAULT;
5139  if (*iter >= '1' && *iter <= '9') {
5140  const char *end;
5141  width = nk_strtoi(iter, &end);
5142  if (end == iter)
5143  width = -1;
5144  else iter = end;
5145  } else if (*iter == '*') {
5146  width = va_arg(args, int);
5147  iter++;
5148  }
5149 
5150  /* precision argument */
5151  precision = NK_DEFAULT;
5152  if (*iter == '.') {
5153  iter++;
5154  if (*iter == '*') {
5155  precision = va_arg(args, int);
5156  iter++;
5157  } else {
5158  const char *end;
5159  precision = nk_strtoi(iter, &end);
5160  if (end == iter)
5161  precision = -1;
5162  else iter = end;
5163  }
5164  }
5165 
5166  /* length modifier */
5167  if (*iter == 'h') {
5168  if (*(iter+1) == 'h') {
5169  arg_type = NK_ARG_TYPE_CHAR;
5170  iter++;
5171  } else arg_type = NK_ARG_TYPE_SHORT;
5172  iter++;
5173  } else if (*iter == 'l') {
5174  arg_type = NK_ARG_TYPE_LONG;
5175  iter++;
5176  } else arg_type = NK_ARG_TYPE_DEFAULT;
5177 
5178  /* specifier */
5179  if (*iter == '%') {
5180  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5181  NK_ASSERT(precision == NK_DEFAULT);
5182  NK_ASSERT(width == NK_DEFAULT);
5183  if (len < buf_size)
5184  buf[len++] = '%';
5185  } else if (*iter == 's') {
5186  /* string */
5187  const char *str = va_arg(args, const char*);
5188  NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
5189  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5190  NK_ASSERT(precision == NK_DEFAULT);
5191  NK_ASSERT(width == NK_DEFAULT);
5192  if (str == buf) return -1;
5193  while (str && *str && len < buf_size)
5194  buf[len++] = *str++;
5195  } else if (*iter == 'n') {
5196  /* current length callback */
5197  signed int *n = va_arg(args, int*);
5198  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5199  NK_ASSERT(precision == NK_DEFAULT);
5200  NK_ASSERT(width == NK_DEFAULT);
5201  if (n) *n = len;
5202  } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
5203  /* signed integer */
5204  long value = 0;
5205  const char *num_iter;
5206  int num_len, num_print, padding;
5207  int cur_precision = NK_MAX(precision, 1);
5208  int cur_width = NK_MAX(width, 0);
5209 
5210  /* retrieve correct value type */
5211  if (arg_type == NK_ARG_TYPE_CHAR)
5212  value = (signed char)va_arg(args, int);
5213  else if (arg_type == NK_ARG_TYPE_SHORT)
5214  value = (signed short)va_arg(args, int);
5215  else if (arg_type == NK_ARG_TYPE_LONG)
5216  value = va_arg(args, signed long);
5217  else if (*iter == 'c')
5218  value = (unsigned char)va_arg(args, int);
5219  else value = va_arg(args, signed int);
5220 
5221  /* convert number to string */
5222  nk_itoa(number_buffer, value);
5223  num_len = nk_strlen(number_buffer);
5224  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5225  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5226  padding = NK_MAX(padding-1, 0);
5227 
5228  /* fill left padding up to a total of `width` characters */
5229  if (!(flag & NK_ARG_FLAG_LEFT)) {
5230  while (padding-- > 0 && (len < buf_size)) {
5231  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5232  buf[len++] = '0';
5233  else buf[len++] = ' ';
5234  }
5235  }
5236 
5237  /* copy string value representation into buffer */
5238  if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
5239  buf[len++] = '+';
5240  else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
5241  buf[len++] = ' ';
5242 
5243  /* fill up to precision number of digits with '0' */
5244  num_print = NK_MAX(cur_precision, num_len);
5245  while (precision && (num_print > num_len) && (len < buf_size)) {
5246  buf[len++] = '0';
5247  num_print--;
5248  }
5249 
5250  /* copy string value representation into buffer */
5251  num_iter = number_buffer;
5252  while (precision && *num_iter && len < buf_size)
5253  buf[len++] = *num_iter++;
5254 
5255  /* fill right padding up to width characters */
5256  if (flag & NK_ARG_FLAG_LEFT) {
5257  while ((padding-- > 0) && (len < buf_size))
5258  buf[len++] = ' ';
5259  }
5260  } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
5261  /* unsigned integer */
5262  unsigned long value = 0;
5263  int num_len = 0, num_print, padding = 0;
5264  int cur_precision = NK_MAX(precision, 1);
5265  int cur_width = NK_MAX(width, 0);
5266  unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
5267 
5268  /* print oct/hex/dec value */
5269  const char *upper_output_format = "0123456789ABCDEF";
5270  const char *lower_output_format = "0123456789abcdef";
5271  const char *output_format = (*iter == 'x') ?
5272  lower_output_format: upper_output_format;
5273 
5274  /* retrieve correct value type */
5275  if (arg_type == NK_ARG_TYPE_CHAR)
5276  value = (unsigned char)va_arg(args, int);
5277  else if (arg_type == NK_ARG_TYPE_SHORT)
5278  value = (unsigned short)va_arg(args, int);
5279  else if (arg_type == NK_ARG_TYPE_LONG)
5280  value = va_arg(args, unsigned long);
5281  else value = va_arg(args, unsigned int);
5282 
5283  do {
5284  /* convert decimal number into hex/oct number */
5285  int digit = output_format[value % base];
5286  if (num_len < NK_MAX_NUMBER_BUFFER)
5287  number_buffer[num_len++] = (char)digit;
5288  value /= base;
5289  } while (value > 0);
5290 
5291  num_print = NK_MAX(cur_precision, num_len);
5292  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5293  if (flag & NK_ARG_FLAG_NUM)
5294  padding = NK_MAX(padding-1, 0);
5295 
5296  /* fill left padding up to a total of `width` characters */
5297  if (!(flag & NK_ARG_FLAG_LEFT)) {
5298  while ((padding-- > 0) && (len < buf_size)) {
5299  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5300  buf[len++] = '0';
5301  else buf[len++] = ' ';
5302  }
5303  }
5304 
5305  /* fill up to precision number of digits */
5306  if (num_print && (flag & NK_ARG_FLAG_NUM)) {
5307  if ((*iter == 'o') && (len < buf_size)) {
5308  buf[len++] = '0';
5309  } else if ((*iter == 'x') && ((len+1) < buf_size)) {
5310  buf[len++] = '0';
5311  buf[len++] = 'x';
5312  } else if ((*iter == 'X') && ((len+1) < buf_size)) {
5313  buf[len++] = '0';
5314  buf[len++] = 'X';
5315  }
5316  }
5317  while (precision && (num_print > num_len) && (len < buf_size)) {
5318  buf[len++] = '0';
5319  num_print--;
5320  }
5321 
5322  /* reverse number direction */
5323  while (num_len > 0) {
5324  if (precision && (len < buf_size))
5325  buf[len++] = number_buffer[num_len-1];
5326  num_len--;
5327  }
5328 
5329  /* fill right padding up to width characters */
5330  if (flag & NK_ARG_FLAG_LEFT) {
5331  while ((padding-- > 0) && (len < buf_size))
5332  buf[len++] = ' ';
5333  }
5334  } else if (*iter == 'f') {
5335  /* floating point */
5336  const char *num_iter;
5337  int cur_precision = (precision < 0) ? 6: precision;
5338  int prefix, cur_width = NK_MAX(width, 0);
5339  double value = va_arg(args, double);
5340  int num_len = 0, frac_len = 0, dot = 0;
5341  int padding = 0;
5342 
5343  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5344  NK_DTOA(number_buffer, value);
5345  num_len = nk_strlen(number_buffer);
5346 
5347  /* calculate padding */
5348  num_iter = number_buffer;
5349  while (*num_iter && *num_iter != '.')
5350  num_iter++;
5351 
5352  prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
5353  padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
5354  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5355  padding = NK_MAX(padding-1, 0);
5356 
5357  /* fill left padding up to a total of `width` characters */
5358  if (!(flag & NK_ARG_FLAG_LEFT)) {
5359  while (padding-- > 0 && (len < buf_size)) {
5360  if (flag & NK_ARG_FLAG_ZERO)
5361  buf[len++] = '0';
5362  else buf[len++] = ' ';
5363  }
5364  }
5365 
5366  /* copy string value representation into buffer */
5367  num_iter = number_buffer;
5368  if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
5369  buf[len++] = '+';
5370  else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
5371  buf[len++] = ' ';
5372  while (*num_iter) {
5373  if (dot) frac_len++;
5374  if (len < buf_size)
5375  buf[len++] = *num_iter;
5376  if (*num_iter == '.') dot = 1;
5377  if (frac_len >= cur_precision) break;
5378  num_iter++;
5379  }
5380 
5381  /* fill number up to precision */
5382  while (frac_len < cur_precision) {
5383  if (!dot && len < buf_size) {
5384  buf[len++] = '.';
5385  dot = 1;
5386  }
5387  if (len < buf_size)
5388  buf[len++] = '0';
5389  frac_len++;
5390  }
5391 
5392  /* fill right padding up to width characters */
5393  if (flag & NK_ARG_FLAG_LEFT) {
5394  while ((padding-- > 0) && (len < buf_size))
5395  buf[len++] = ' ';
5396  }
5397  } else {
5398  /* Specifier not supported: g,G,e,E,p,z */
5399  NK_ASSERT(0 && "specifier is not supported!");
5400  return result;
5401  }
5402  }
5403  buf[(len >= buf_size)?(buf_size-1):len] = 0;
5404  result = (len >= buf_size)?-1:len;
5405  return result;
5406 }
5407 #endif
5408 
5409 NK_INTERN int
5410 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
5411 {
5412  int result = -1;
5413  NK_ASSERT(buf);
5414  NK_ASSERT(buf_size);
5415  if (!buf || !buf_size || !fmt) return 0;
5416 #ifdef NK_INCLUDE_STANDARD_IO
5417  result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
5418  result = (result >= buf_size) ? -1: result;
5419  buf[buf_size-1] = 0;
5420 #else
5421  result = nk_vsnprintf(buf, buf_size, fmt, args);
5422 #endif
5423  return result;
5424 }
5425 #endif
5426 
5427 NK_API nk_hash
5428 nk_murmur_hash(const void * key, int len, nk_hash seed)
5429 {
5430  /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
5431  #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
5432  union {const nk_uint *i; const nk_byte *b;} conv = {0};
5433  const nk_byte *data = (const nk_byte*)key;
5434  const int nblocks = len/4;
5435  nk_uint h1 = seed;
5436  const nk_uint c1 = 0xcc9e2d51;
5437  const nk_uint c2 = 0x1b873593;
5438  const nk_byte *tail;
5439  const nk_uint *blocks;
5440  nk_uint k1;
5441  int i;
5442 
5443  /* body */
5444  if (!key) return 0;
5445  conv.b = (data + nblocks*4);
5446  blocks = (const nk_uint*)conv.i;
5447  for (i = -nblocks; i; ++i) {
5448  k1 = blocks[i];
5449  k1 *= c1;
5450  k1 = NK_ROTL(k1,15);
5451  k1 *= c2;
5452 
5453  h1 ^= k1;
5454  h1 = NK_ROTL(h1,13);
5455  h1 = h1*5+0xe6546b64;
5456  }
5457 
5458  /* tail */
5459  tail = (const nk_byte*)(data + nblocks*4);
5460  k1 = 0;
5461  switch (len & 3) {
5462  case 3: k1 ^= (nk_uint)(tail[2] << 16);
5463  case 2: k1 ^= (nk_uint)(tail[1] << 8u);
5464  case 1: k1 ^= tail[0];
5465  k1 *= c1;
5466  k1 = NK_ROTL(k1,15);
5467  k1 *= c2;
5468  h1 ^= k1;
5469  default: break;
5470  }
5471 
5472  /* finalization */
5473  h1 ^= (nk_uint)len;
5474  /* fmix32 */
5475  h1 ^= h1 >> 16;
5476  h1 *= 0x85ebca6b;
5477  h1 ^= h1 >> 13;
5478  h1 *= 0xc2b2ae35;
5479  h1 ^= h1 >> 16;
5480 
5481  #undef NK_ROTL
5482  return h1;
5483 }
5484 
5485 #ifdef NK_INCLUDE_STANDARD_IO
5486 NK_INTERN char*
5487 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
5488 {
5489  char *buf;
5490  FILE *fd;
5491  long ret;
5492 
5493  NK_ASSERT(path);
5494  NK_ASSERT(siz);
5495  NK_ASSERT(alloc);
5496  if (!path || !siz || !alloc)
5497  return 0;
5498 
5499  fd = fopen(path, "rb");
5500  if (!fd) return 0;
5501  fseek(fd, 0, SEEK_END);
5502  ret = ftell(fd);
5503  if (ret < 0) {
5504  fclose(fd);
5505  return 0;
5506  }
5507  *siz = (nk_size)ret;
5508  fseek(fd, 0, SEEK_SET);
5509  buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
5510  NK_ASSERT(buf);
5511  if (!buf) {
5512  fclose(fd);
5513  return 0;
5514  }
5515  *siz = (nk_size)fread(buf, *siz, 1, fd);
5516  fclose(fd);
5517  return buf;
5518 }
5519 #endif
5520 
5521 /*
5522  * ==============================================================
5523  *
5524  * COLOR
5525  *
5526  * ===============================================================
5527  */
5528 NK_INTERN int
5529 nk_parse_hex(const char *p, int length)
5530 {
5531  int i = 0;
5532  int len = 0;
5533  while (len < length) {
5534  i <<= 4;
5535  if (p[len] >= 'a' && p[len] <= 'f')
5536  i += ((p[len] - 'a') + 10);
5537  else if (p[len] >= 'A' && p[len] <= 'F')
5538  i += ((p[len] - 'A') + 10);
5539  else i += (p[len] - '0');
5540  len++;
5541  }
5542  return i;
5543 }
5544 
5545 NK_API struct nk_color
5546 nk_rgba(int r, int g, int b, int a)
5547 {
5548  struct nk_color ret;
5549  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5550  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5551  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5552  ret.a = (nk_byte)NK_CLAMP(0, a, 255);
5553  return ret;
5554 }
5555 
5556 NK_API struct nk_color
5557 nk_rgb_hex(const char *rgb)
5558 {
5559  struct nk_color col;
5560  const char *c = rgb;
5561  if (*c == '#') c++;
5562  col.r = (nk_byte)nk_parse_hex(c, 2);
5563  col.g = (nk_byte)nk_parse_hex(c+2, 2);
5564  col.b = (nk_byte)nk_parse_hex(c+4, 2);
5565  col.a = 255;
5566  return col;
5567 }
5568 
5569 NK_API struct nk_color
5570 nk_rgba_hex(const char *rgb)
5571 {
5572  struct nk_color col;
5573  const char *c = rgb;
5574  if (*c == '#') c++;
5575  col.r = (nk_byte)nk_parse_hex(c, 2);
5576  col.g = (nk_byte)nk_parse_hex(c+2, 2);
5577  col.b = (nk_byte)nk_parse_hex(c+4, 2);
5578  col.a = (nk_byte)nk_parse_hex(c+6, 2);
5579  return col;
5580 }
5581 
5582 NK_API void
5583 nk_color_hex_rgba(char *output, struct nk_color col)
5584 {
5585  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5586  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5587  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5588  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5589  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5590  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5591  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5592  output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
5593  output[7] = (char)NK_TO_HEX((col.a & 0x0F));
5594  output[8] = '\0';
5595  #undef NK_TO_HEX
5596 }
5597 
5598 NK_API void
5599 nk_color_hex_rgb(char *output, struct nk_color col)
5600 {
5601  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5602  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5603  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5604  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5605  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5606  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5607  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5608  output[6] = '\0';
5609  #undef NK_TO_HEX
5610 }
5611 
5612 NK_API struct nk_color
5613 nk_rgba_iv(const int *c)
5614 {
5615  return nk_rgba(c[0], c[1], c[2], c[3]);
5616 }
5617 
5618 NK_API struct nk_color
5619 nk_rgba_bv(const nk_byte *c)
5620 {
5621  return nk_rgba(c[0], c[1], c[2], c[3]);
5622 }
5623 
5624 NK_API struct nk_color
5625 nk_rgb(int r, int g, int b)
5626 {
5627  struct nk_color ret;
5628  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5629  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5630  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5631  ret.a = (nk_byte)255;
5632  return ret;
5633 }
5634 
5635 NK_API struct nk_color
5636 nk_rgb_iv(const int *c)
5637 {
5638  return nk_rgb(c[0], c[1], c[2]);
5639 }
5640 
5641 NK_API struct nk_color
5642 nk_rgb_bv(const nk_byte* c)
5643 {
5644  return nk_rgb(c[0], c[1], c[2]);
5645 }
5646 
5647 NK_API struct nk_color
5648 nk_rgba_u32(nk_uint in)
5649 {
5650  struct nk_color ret;
5651  ret.r = (in & 0xFF);
5652  ret.g = ((in >> 8) & 0xFF);
5653  ret.b = ((in >> 16) & 0xFF);
5654  ret.a = (nk_byte)((in >> 24) & 0xFF);
5655  return ret;
5656 }
5657 
5658 NK_API struct nk_color
5659 nk_rgba_f(float r, float g, float b, float a)
5660 {
5661  struct nk_color ret;
5662  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5663  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5664  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5665  ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
5666  return ret;
5667 }
5668 
5669 NK_API struct nk_color
5670 nk_rgba_fv(const float *c)
5671 {
5672  return nk_rgba_f(c[0], c[1], c[2], c[3]);
5673 }
5674 
5675 NK_API struct nk_color
5676 nk_rgb_f(float r, float g, float b)
5677 {
5678  struct nk_color ret;
5679  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5680  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5681  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5682  ret.a = 255;
5683  return ret;
5684 }
5685 
5686 NK_API struct nk_color
5687 nk_rgb_fv(const float *c)
5688 {
5689  return nk_rgb_f(c[0], c[1], c[2]);
5690 }
5691 
5692 NK_API struct nk_color
5693 nk_hsv(int h, int s, int v)
5694 {
5695  return nk_hsva(h, s, v, 255);
5696 }
5697 
5698 NK_API struct nk_color
5699 nk_hsv_iv(const int *c)
5700 {
5701  return nk_hsv(c[0], c[1], c[2]);
5702 }
5703 
5704 NK_API struct nk_color
5705 nk_hsv_bv(const nk_byte *c)
5706 {
5707  return nk_hsv(c[0], c[1], c[2]);
5708 }
5709 
5710 NK_API struct nk_color
5711 nk_hsv_f(float h, float s, float v)
5712 {
5713  return nk_hsva_f(h, s, v, 1.0f);
5714 }
5715 
5716 NK_API struct nk_color
5717 nk_hsv_fv(const float *c)
5718 {
5719  return nk_hsv_f(c[0], c[1], c[2]);
5720 }
5721 
5722 NK_API struct nk_color
5723 nk_hsva(int h, int s, int v, int a)
5724 {
5725  float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
5726  float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
5727  float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
5728  float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
5729  return nk_hsva_f(hf, sf, vf, af);
5730 }
5731 
5732 NK_API struct nk_color
5733 nk_hsva_iv(const int *c)
5734 {
5735  return nk_hsva(c[0], c[1], c[2], c[3]);
5736 }
5737 
5738 NK_API struct nk_color
5739 nk_hsva_bv(const nk_byte *c)
5740 {
5741  return nk_hsva(c[0], c[1], c[2], c[3]);
5742 }
5743 
5744 NK_API struct nk_color
5745 nk_hsva_f(float h, float s, float v, float a)
5746 {
5747  struct nk_colorf out = {0,0,0,0};
5748  float p, q, t, f;
5749  int i;
5750 
5751  if (s <= 0.0f) {
5752  out.r = v; out.g = v; out.b = v;
5753  return nk_rgb_f(out.r, out.g, out.b);
5754  }
5755 
5756  h = h / (60.0f/360.0f);
5757  i = (int)h;
5758  f = h - (float)i;
5759  p = v * (1.0f - s);
5760  q = v * (1.0f - (s * f));
5761  t = v * (1.0f - s * (1.0f - f));
5762 
5763  switch (i) {
5764  case 0: default: out.r = v; out.g = t; out.b = p; break;
5765  case 1: out.r = q; out.g = v; out.b = p; break;
5766  case 2: out.r = p; out.g = v; out.b = t; break;
5767  case 3: out.r = p; out.g = q; out.b = v; break;
5768  case 4: out.r = t; out.g = p; out.b = v; break;
5769  case 5: out.r = v; out.g = p; out.b = q; break;
5770  }
5771  return nk_rgba_f(out.r, out.g, out.b, a);
5772 }
5773 
5774 NK_API struct nk_color
5775 nk_hsva_fv(const float *c)
5776 {
5777  return nk_hsva_f(c[0], c[1], c[2], c[3]);
5778 }
5779 
5780 NK_API nk_uint
5781 nk_color_u32(struct nk_color in)
5782 {
5783  nk_uint out = (nk_uint)in.r;
5784  out |= ((nk_uint)in.g << 8);
5785  out |= ((nk_uint)in.b << 16);
5786  out |= ((nk_uint)in.a << 24);
5787  return out;
5788 }
5789 
5790 NK_API void
5791 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
5792 {
5793  NK_STORAGE const float s = 1.0f/255.0f;
5794  *r = (float)in.r * s;
5795  *g = (float)in.g * s;
5796  *b = (float)in.b * s;
5797  *a = (float)in.a * s;
5798 }
5799 
5800 NK_API void
5801 nk_color_fv(float *c, struct nk_color in)
5802 {
5803  nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
5804 }
5805 
5806 NK_API void
5807 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
5808 {
5809  NK_STORAGE const double s = 1.0/255.0;
5810  *r = (double)in.r * s;
5811  *g = (double)in.g * s;
5812  *b = (double)in.b * s;
5813  *a = (double)in.a * s;
5814 }
5815 
5816 NK_API void
5817 nk_color_dv(double *c, struct nk_color in)
5818 {
5819  nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
5820 }
5821 
5822 NK_API void
5823 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
5824 {
5825  float a;
5826  nk_color_hsva_f(out_h, out_s, out_v, &a, in);
5827 }
5828 
5829 NK_API void
5830 nk_color_hsv_fv(float *out, struct nk_color in)
5831 {
5832  float a;
5833  nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
5834 }
5835 
5836 NK_API void
5837 nk_color_hsva_f(float *out_h, float *out_s,
5838  float *out_v, float *out_a, struct nk_color in)
5839 {
5840  float chroma;
5841  float K = 0.0f;
5842  float r,g,b,a;
5843 
5844  nk_color_f(&r,&g,&b,&a, in);
5845  if (g < b) {
5846  const float t = g; g = b; b = t;
5847  K = -1.f;
5848  }
5849  if (r < g) {
5850  const float t = r; r = g; g = t;
5851  K = -2.f/6.0f - K;
5852  }
5853  chroma = r - ((g < b) ? g: b);
5854  *out_h = NK_ABS(K + (g - b)/(6.0f * chroma + 1e-20f));
5855  *out_s = chroma / (r + 1e-20f);
5856  *out_v = r;
5857  *out_a = (float)in.a / 255.0f;
5858 }
5859 
5860 NK_API void
5861 nk_color_hsva_fv(float *out, struct nk_color in)
5862 {
5863  nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
5864 }
5865 
5866 NK_API void
5867 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
5868  int *out_a, struct nk_color in)
5869 {
5870  float h,s,v,a;
5871  nk_color_hsva_f(&h, &s, &v, &a, in);
5872  *out_h = (nk_byte)(h * 255.0f);
5873  *out_s = (nk_byte)(s * 255.0f);
5874  *out_v = (nk_byte)(v * 255.0f);
5875  *out_a = (nk_byte)(a * 255.0f);
5876 }
5877 
5878 NK_API void
5879 nk_color_hsva_iv(int *out, struct nk_color in)
5880 {
5881  nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
5882 }
5883 
5884 NK_API void
5885 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
5886 {
5887  int tmp[4];
5888  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
5889  out[0] = (nk_byte)tmp[0];
5890  out[1] = (nk_byte)tmp[1];
5891  out[2] = (nk_byte)tmp[2];
5892  out[3] = (nk_byte)tmp[3];
5893 }
5894 
5895 NK_API void
5896 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
5897 {
5898  int tmp[4];
5899  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
5900  *h = (nk_byte)tmp[0];
5901  *s = (nk_byte)tmp[1];
5902  *v = (nk_byte)tmp[2];
5903  *a = (nk_byte)tmp[3];
5904 }
5905 
5906 NK_API void
5907 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
5908 {
5909  int a;
5910  nk_color_hsva_i(out_h, out_s, out_v, &a, in);
5911 }
5912 
5913 NK_API void
5914 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
5915 {
5916  int tmp[4];
5917  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
5918  *out_h = (nk_byte)tmp[0];
5919  *out_s = (nk_byte)tmp[1];
5920  *out_v = (nk_byte)tmp[2];
5921 }
5922 
5923 NK_API void
5924 nk_color_hsv_iv(int *out, struct nk_color in)
5925 {
5926  nk_color_hsv_i(&out[0], &out[1], &out[2], in);
5927 }
5928 
5929 NK_API void
5930 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
5931 {
5932  int tmp[4];
5933  nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
5934  out[0] = (nk_byte)tmp[0];
5935  out[1] = (nk_byte)tmp[1];
5936  out[2] = (nk_byte)tmp[2];
5937 }
5938 /*
5939  * ==============================================================
5940  *
5941  * IMAGE
5942  *
5943  * ===============================================================
5944  */
5945 NK_API nk_handle
5946 nk_handle_ptr(void *ptr)
5947 {
5948  nk_handle handle = {0};
5949  handle.ptr = ptr;
5950  return handle;
5951 }
5952 
5953 NK_API nk_handle
5954 nk_handle_id(int id)
5955 {
5956  nk_handle handle;
5957  nk_zero_struct(handle);
5958  handle.id = id;
5959  return handle;
5960 }
5961 
5962 NK_API struct nk_image
5963 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
5964 {
5965  struct nk_image s;
5966  nk_zero(&s, sizeof(s));
5967  s.handle.ptr = ptr;
5968  s.w = w; s.h = h;
5969  s.region[0] = (unsigned short)r.x;
5970  s.region[1] = (unsigned short)r.y;
5971  s.region[2] = (unsigned short)r.w;
5972  s.region[3] = (unsigned short)r.h;
5973  return s;
5974 }
5975 
5976 NK_API struct nk_image
5977 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
5978 {
5979  struct nk_image s;
5980  nk_zero(&s, sizeof(s));
5981  s.handle.id = id;
5982  s.w = w; s.h = h;
5983  s.region[0] = (unsigned short)r.x;
5984  s.region[1] = (unsigned short)r.y;
5985  s.region[2] = (unsigned short)r.w;
5986  s.region[3] = (unsigned short)r.h;
5987  return s;
5988 }
5989 
5990 NK_API struct nk_image
5991 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
5992  struct nk_rect r)
5993 {
5994  struct nk_image s;
5995  nk_zero(&s, sizeof(s));
5996  s.handle = handle;
5997  s.w = w; s.h = h;
5998  s.region[0] = (unsigned short)r.x;
5999  s.region[1] = (unsigned short)r.y;
6000  s.region[2] = (unsigned short)r.w;
6001  s.region[3] = (unsigned short)r.h;
6002  return s;
6003 }
6004 
6005 NK_API struct nk_image
6006 nk_image_handle(nk_handle handle)
6007 {
6008  struct nk_image s;
6009  nk_zero(&s, sizeof(s));
6010  s.handle = handle;
6011  s.w = 0; s.h = 0;
6012  s.region[0] = 0;
6013  s.region[1] = 0;
6014  s.region[2] = 0;
6015  s.region[3] = 0;
6016  return s;
6017 }
6018 
6019 NK_API struct nk_image
6020 nk_image_ptr(void *ptr)
6021 {
6022  struct nk_image s;
6023  nk_zero(&s, sizeof(s));
6024  NK_ASSERT(ptr);
6025  s.handle.ptr = ptr;
6026  s.w = 0; s.h = 0;
6027  s.region[0] = 0;
6028  s.region[1] = 0;
6029  s.region[2] = 0;
6030  s.region[3] = 0;
6031  return s;
6032 }
6033 
6034 NK_API struct nk_image
6035 nk_image_id(int id)
6036 {
6037  struct nk_image s;
6038  nk_zero(&s, sizeof(s));
6039  s.handle.id = id;
6040  s.w = 0; s.h = 0;
6041  s.region[0] = 0;
6042  s.region[1] = 0;
6043  s.region[2] = 0;
6044  s.region[3] = 0;
6045  return s;
6046 }
6047 
6048 NK_API int
6049 nk_image_is_subimage(const struct nk_image* img)
6050 {
6051  NK_ASSERT(img);
6052  return !(img->w == 0 && img->h == 0);
6053 }
6054 
6055 NK_INTERN void
6056 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6057  float x1, float y1)
6058 {
6059  NK_ASSERT(a);
6060  NK_ASSERT(clip);
6061  clip->x = NK_MAX(a->x, x0);
6062  clip->y = NK_MAX(a->y, y0);
6063  clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6064  clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6065  clip->w = NK_MAX(0, clip->w);
6066  clip->h = NK_MAX(0, clip->h);
6067 }
6068 
6069 NK_API void
6070 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
6071  float pad_x, float pad_y, enum nk_heading direction)
6072 {
6073  float w_half, h_half;
6074  NK_ASSERT(result);
6075 
6076  r.w = NK_MAX(2 * pad_x, r.w);
6077  r.h = NK_MAX(2 * pad_y, r.h);
6078  r.w = r.w - 2 * pad_x;
6079  r.h = r.h - 2 * pad_y;
6080 
6081  r.x = r.x + pad_x;
6082  r.y = r.y + pad_y;
6083 
6084  w_half = r.w / 2.0f;
6085  h_half = r.h / 2.0f;
6086 
6087  if (direction == NK_UP) {
6088  result[0] = nk_vec2(r.x + w_half, r.y);
6089  result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6090  result[2] = nk_vec2(r.x, r.y + r.h);
6091  } else if (direction == NK_RIGHT) {
6092  result[0] = nk_vec2(r.x, r.y);
6093  result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6094  result[2] = nk_vec2(r.x, r.y + r.h);
6095  } else if (direction == NK_DOWN) {
6096  result[0] = nk_vec2(r.x, r.y);
6097  result[1] = nk_vec2(r.x + r.w, r.y);
6098  result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6099  } else {
6100  result[0] = nk_vec2(r.x, r.y + h_half);
6101  result[1] = nk_vec2(r.x + r.w, r.y);
6102  result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6103  }
6104 }
6105 
6106 NK_INTERN int
6107 nk_text_clamp(const struct nk_user_font *font, const char *text,
6108  int text_len, float space, int *glyphs, float *text_width,
6109  nk_rune *sep_list, int sep_count)
6110 {
6111  int i = 0;
6112  int glyph_len = 0;
6113  float last_width = 0;
6114  nk_rune unicode = 0;
6115  float width = 0;
6116  int len = 0;
6117  int g = 0;
6118  float s;
6119 
6120  int sep_len = 0;
6121  int sep_g = 0;
6122  float sep_width = 0;
6123  sep_count = NK_MAX(sep_count,0);
6124 
6125  glyph_len = nk_utf_decode(text, &unicode, text_len);
6126  while (glyph_len && (width < space) && (len < text_len)) {
6127  len += glyph_len;
6128  s = font->width(font->userdata, font->height, text, len);
6129  for (i = 0; i < sep_count; ++i) {
6130  if (unicode != sep_list[i]) continue;
6131  sep_width = last_width = width;
6132  sep_g = g+1;
6133  sep_len = len;
6134  break;
6135  }
6136  if (i == NK_MAX(sep_count,0)){
6137  last_width = sep_width = width;
6138  sep_g = g+1;
6139  }
6140  width = s;
6141  glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
6142  g++;
6143  }
6144  if (len >= text_len) {
6145  *glyphs = g;
6146  *text_width = last_width;
6147  return len;
6148  } else {
6149  *glyphs = sep_g;
6150  *text_width = sep_width;
6151  return (!sep_len) ? len: sep_len;
6152  }
6153 }
6154 
6155 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
6156 NK_INTERN struct nk_vec2
6157 nk_text_calculate_text_bounds(const struct nk_user_font *font,
6158  const char *begin, int byte_len, float row_height, const char **remaining,
6159  struct nk_vec2 *out_offset, int *glyphs, int op)
6160 {
6161  float line_height = row_height;
6162  struct nk_vec2 text_size = nk_vec2(0,0);
6163  float line_width = 0.0f;
6164 
6165  float glyph_width;
6166  int glyph_len = 0;
6167  nk_rune unicode = 0;
6168  int text_len = 0;
6169  if (!begin || byte_len <= 0 || !font)
6170  return nk_vec2(0,row_height);
6171 
6172  glyph_len = nk_utf_decode(begin, &unicode, byte_len);
6173  if (!glyph_len) return text_size;
6174  glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
6175 
6176  *glyphs = 0;
6177  while ((text_len < byte_len) && glyph_len) {
6178  if (unicode == '\n') {
6179  text_size.x = NK_MAX(text_size.x, line_width);
6180  text_size.y += line_height;
6181  line_width = 0;
6182  *glyphs+=1;
6183  if (op == NK_STOP_ON_NEW_LINE)
6184  break;
6185 
6186  text_len++;
6187  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6188  continue;
6189  }
6190 
6191  if (unicode == '\r') {
6192  text_len++;
6193  *glyphs+=1;
6194  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6195  continue;
6196  }
6197 
6198  *glyphs = *glyphs + 1;
6199  text_len += glyph_len;
6200  line_width += (float)glyph_width;
6201  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6202  glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
6203  continue;
6204  }
6205 
6206  if (text_size.x < line_width)
6207  text_size.x = line_width;
6208  if (out_offset)
6209  *out_offset = nk_vec2(line_width, text_size.y + line_height);
6210  if (line_width > 0 || text_size.y == 0.0f)
6211  text_size.y += line_height;
6212  if (remaining)
6213  *remaining = begin+text_len;
6214  return text_size;
6215 }
6216 
6217 /* ==============================================================
6218  *
6219  * UTF-8
6220  *
6221  * ===============================================================*/
6222 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
6223 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
6224 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
6225 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
6226 
6227 NK_INTERN int
6228 nk_utf_validate(nk_rune *u, int i)
6229 {
6230  NK_ASSERT(u);
6231  if (!u) return 0;
6232  if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
6233  NK_BETWEEN(*u, 0xD800, 0xDFFF))
6234  *u = NK_UTF_INVALID;
6235  for (i = 1; *u > nk_utfmax[i]; ++i);
6236  return i;
6237 }
6238 
6239 NK_INTERN nk_rune
6240 nk_utf_decode_byte(char c, int *i)
6241 {
6242  NK_ASSERT(i);
6243  if (!i) return 0;
6244  for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
6245  if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
6246  return (nk_byte)(c & ~nk_utfmask[*i]);
6247  }
6248  return 0;
6249 }
6250 
6251 NK_API int
6252 nk_utf_decode(const char *c, nk_rune *u, int clen)
6253 {
6254  int i, j, len, type=0;
6255  nk_rune udecoded;
6256 
6257  NK_ASSERT(c);
6258  NK_ASSERT(u);
6259 
6260  if (!c || !u) return 0;
6261  if (!clen) return 0;
6262  *u = NK_UTF_INVALID;
6263 
6264  udecoded = nk_utf_decode_byte(c[0], &len);
6265  if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
6266  return 1;
6267 
6268  for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
6269  udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
6270  if (type != 0)
6271  return j;
6272  }
6273  if (j < len)
6274  return 0;
6275  *u = udecoded;
6276  nk_utf_validate(u, len);
6277  return len;
6278 }
6279 
6280 NK_INTERN char
6281 nk_utf_encode_byte(nk_rune u, int i)
6282 {
6283  return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
6284 }
6285 
6286 NK_API int
6287 nk_utf_encode(nk_rune u, char *c, int clen)
6288 {
6289  int len, i;
6290  len = nk_utf_validate(&u, 0);
6291  if (clen < len || !len || len > NK_UTF_SIZE)
6292  return 0;
6293 
6294  for (i = len - 1; i != 0; --i) {
6295  c[i] = nk_utf_encode_byte(u, 0);
6296  u >>= 6;
6297  }
6298  c[0] = nk_utf_encode_byte(u, len);
6299  return len;
6300 }
6301 
6302 NK_API int
6303 nk_utf_len(const char *str, int len)
6304 {
6305  const char *text;
6306  int glyphs = 0;
6307  int text_len;
6308  int glyph_len;
6309  int src_len = 0;
6310  nk_rune unicode;
6311 
6312  NK_ASSERT(str);
6313  if (!str || !len) return 0;
6314 
6315  text = str;
6316  text_len = len;
6317  glyph_len = nk_utf_decode(text, &unicode, text_len);
6318  while (glyph_len && src_len < len) {
6319  glyphs++;
6320  src_len = src_len + glyph_len;
6321  glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
6322  }
6323  return glyphs;
6324 }
6325 
6326 NK_API const char*
6327 nk_utf_at(const char *buffer, int length, int index,
6328  nk_rune *unicode, int *len)
6329 {
6330  int i = 0;
6331  int src_len = 0;
6332  int glyph_len = 0;
6333  const char *text;
6334  int text_len;
6335 
6336  NK_ASSERT(buffer);
6337  NK_ASSERT(unicode);
6338  NK_ASSERT(len);
6339 
6340  if (!buffer || !unicode || !len) return 0;
6341  if (index < 0) {
6342  *unicode = NK_UTF_INVALID;
6343  *len = 0;
6344  return 0;
6345  }
6346 
6347  text = buffer;
6348  text_len = length;
6349  glyph_len = nk_utf_decode(text, unicode, text_len);
6350  while (glyph_len) {
6351  if (i == index) {
6352  *len = glyph_len;
6353  break;
6354  }
6355 
6356  i++;
6357  src_len = src_len + glyph_len;
6358  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
6359  }
6360  if (i != index) return 0;
6361  return buffer + src_len;
6362 }
6363 
6364 /* ==============================================================
6365  *
6366  * BUFFER
6367  *
6368  * ===============================================================*/
6369 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6370 NK_INTERN void* nk_malloc(nk_handle unused, void *old,nk_size size)
6371 {NK_UNUSED(unused); NK_UNUSED(old); return malloc(size);}
6372 NK_INTERN void nk_mfree(nk_handle unused, void *ptr)
6373 {NK_UNUSED(unused); free(ptr);}
6374 
6375 NK_API void
6376 nk_buffer_init_default(struct nk_buffer *buffer)
6377 {
6378  struct nk_allocator alloc;
6379  alloc.userdata.ptr = 0;
6380  alloc.alloc = nk_malloc;
6381  alloc.free = nk_mfree;
6382  nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
6383 }
6384 #endif
6385 
6386 NK_API void
6387 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
6388  nk_size initial_size)
6389 {
6390  NK_ASSERT(b);
6391  NK_ASSERT(a);
6392  NK_ASSERT(initial_size);
6393  if (!b || !a || !initial_size) return;
6394 
6395  nk_zero(b, sizeof(*b));
6396  b->type = NK_BUFFER_DYNAMIC;
6397  b->memory.ptr = a->alloc(a->userdata,0, initial_size);
6398  b->memory.size = initial_size;
6399  b->size = initial_size;
6400  b->grow_factor = 2.0f;
6401  b->pool = *a;
6402 }
6403 
6404 NK_API void
6405 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
6406 {
6407  NK_ASSERT(b);
6408  NK_ASSERT(m);
6409  NK_ASSERT(size);
6410  if (!b || !m || !size) return;
6411 
6412  nk_zero(b, sizeof(*b));
6413  b->type = NK_BUFFER_FIXED;
6414  b->memory.ptr = m;
6415  b->memory.size = size;
6416  b->size = size;
6417 }
6418 
6419 NK_INTERN void*
6420 nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment,
6421  enum nk_buffer_allocation_type type)
6422 {
6423  void *memory = 0;
6424  switch (type) {
6425  default:
6426  case NK_BUFFER_MAX:
6427  case NK_BUFFER_FRONT:
6428  if (align) {
6429  memory = NK_ALIGN_PTR(unaligned, align);
6430  *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
6431  } else {
6432  memory = unaligned;
6433  *alignment = 0;
6434  }
6435  break;
6436  case NK_BUFFER_BACK:
6437  if (align) {
6438  memory = NK_ALIGN_PTR_BACK(unaligned, align);
6439  *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
6440  } else {
6441  memory = unaligned;
6442  *alignment = 0;
6443  }
6444  break;
6445  }
6446  return memory;
6447 }
6448 
6449 NK_INTERN void*
6450 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
6451 {
6452  void *temp;
6453  nk_size buffer_size;
6454 
6455  NK_ASSERT(b);
6456  NK_ASSERT(size);
6457  if (!b || !size || !b->pool.alloc || !b->pool.free)
6458  return 0;
6459 
6460  buffer_size = b->memory.size;
6461  temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
6462  NK_ASSERT(temp);
6463  if (!temp) return 0;
6464 
6465  *size = capacity;
6466  if (temp != b->memory.ptr) {
6467  NK_MEMCPY(temp, b->memory.ptr, buffer_size);
6468  b->pool.free(b->pool.userdata, b->memory.ptr);
6469  }
6470 
6471  if (b->size == buffer_size) {
6472  /* no back buffer so just set correct size */
6473  b->size = capacity;
6474  return temp;
6475  } else {
6476  /* copy back buffer to the end of the new buffer */
6477  void *dst, *src;
6478  nk_size back_size;
6479  back_size = buffer_size - b->size;
6480  dst = nk_ptr_add(void, temp, capacity - back_size);
6481  src = nk_ptr_add(void, temp, b->size);
6482  NK_MEMCPY(dst, src, back_size);
6483  b->size = capacity - back_size;
6484  }
6485  return temp;
6486 }
6487 
6488 NK_INTERN void*
6489 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
6490  nk_size size, nk_size align)
6491 {
6492  int full;
6493  nk_size alignment;
6494  void *unaligned;
6495  void *memory;
6496 
6497  NK_ASSERT(b);
6498  NK_ASSERT(size);
6499  if (!b || !size) return 0;
6500  b->needed += size;
6501 
6502  /* calculate total size with needed alignment + size */
6503  if (type == NK_BUFFER_FRONT)
6504  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6505  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6506  memory = nk_buffer_align(unaligned, align, &alignment, type);
6507 
6508  /* check if buffer has enough memory*/
6509  if (type == NK_BUFFER_FRONT)
6510  full = ((b->allocated + size + alignment) > b->size);
6511  else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
6512 
6513  if (full) {
6514  nk_size capacity;
6515  if (b->type != NK_BUFFER_DYNAMIC)
6516  return 0;
6517  NK_ASSERT(b->pool.alloc && b->pool.free);
6518  if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
6519  return 0;
6520 
6521  /* buffer is full so allocate bigger buffer if dynamic */
6522  capacity = (nk_size)((float)b->memory.size * b->grow_factor);
6523  capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
6524  b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
6525  if (!b->memory.ptr) return 0;
6526 
6527  /* align newly allocated pointer */
6528  if (type == NK_BUFFER_FRONT)
6529  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6530  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6531  memory = nk_buffer_align(unaligned, align, &alignment, type);
6532  }
6533 
6534  if (type == NK_BUFFER_FRONT)
6535  b->allocated += size + alignment;
6536  else b->size -= (size + alignment);
6537  b->needed += alignment;
6538  b->calls++;
6539  return memory;
6540 }
6541 
6542 NK_API void
6544  const void *memory, nk_size size, nk_size align)
6545 {
6546  void *mem = nk_buffer_alloc(b, type, size, align);
6547  if (!mem) return;
6548  NK_MEMCPY(mem, memory, size);
6549 }
6550 
6551 NK_API void
6552 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
6553 {
6554  NK_ASSERT(buffer);
6555  if (!buffer) return;
6556  buffer->marker[type].active = nk_true;
6557  if (type == NK_BUFFER_BACK)
6558  buffer->marker[type].offset = buffer->size;
6559  else buffer->marker[type].offset = buffer->allocated;
6560 }
6561 
6562 NK_API void
6563 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
6564 {
6565  NK_ASSERT(buffer);
6566  if (!buffer) return;
6567  if (type == NK_BUFFER_BACK) {
6568  /* reset back buffer either back to marker or empty */
6569  buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
6570  if (buffer->marker[type].active)
6571  buffer->size = buffer->marker[type].offset;
6572  else buffer->size = buffer->memory.size;
6573  buffer->marker[type].active = nk_false;
6574  } else {
6575  /* reset front buffer either back to back marker or empty */
6576  buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
6577  if (buffer->marker[type].active)
6578  buffer->allocated = buffer->marker[type].offset;
6579  else buffer->allocated = 0;
6580  buffer->marker[type].active = nk_false;
6581  }
6582 }
6583 
6584 NK_API void
6585 nk_buffer_clear(struct nk_buffer *b)
6586 {
6587  NK_ASSERT(b);
6588  if (!b) return;
6589  b->allocated = 0;
6590  b->size = b->memory.size;
6591  b->calls = 0;
6592  b->needed = 0;
6593 }
6594 
6595 NK_API void
6596 nk_buffer_free(struct nk_buffer *b)
6597 {
6598  NK_ASSERT(b);
6599  if (!b || !b->memory.ptr) return;
6600  if (b->type == NK_BUFFER_FIXED) return;
6601  if (!b->pool.free) return;
6602  NK_ASSERT(b->pool.free);
6603  b->pool.free(b->pool.userdata, b->memory.ptr);
6604 }
6605 
6606 NK_API void
6607 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
6608 {
6609  NK_ASSERT(b);
6610  NK_ASSERT(s);
6611  if (!s || !b) return;
6612  s->allocated = b->allocated;
6613  s->size = b->memory.size;
6614  s->needed = b->needed;
6615  s->memory = b->memory.ptr;
6616  s->calls = b->calls;
6617 }
6618 
6619 NK_API void*
6620 nk_buffer_memory(struct nk_buffer *buffer)
6621 {
6622  NK_ASSERT(buffer);
6623  if (!buffer) return 0;
6624  return buffer->memory.ptr;
6625 }
6626 
6627 NK_API const void*
6628 nk_buffer_memory_const(const struct nk_buffer *buffer)
6629 {
6630  NK_ASSERT(buffer);
6631  if (!buffer) return 0;
6632  return buffer->memory.ptr;
6633 }
6634 
6635 NK_API nk_size
6636 nk_buffer_total(struct nk_buffer *buffer)
6637 {
6638  NK_ASSERT(buffer);
6639  if (!buffer) return 0;
6640  return buffer->memory.size;
6641 }
6642 
6643 /*
6644  * ==============================================================
6645  *
6646  * STRING
6647  *
6648  * ===============================================================
6649  */
6650 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6651 NK_API void
6652 nk_str_init_default(struct nk_str *str)
6653 {
6654  struct nk_allocator alloc;
6655  alloc.userdata.ptr = 0;
6656  alloc.alloc = nk_malloc;
6657  alloc.free = nk_mfree;
6658  nk_buffer_init(&str->buffer, &alloc, 32);
6659  str->len = 0;
6660 }
6661 #endif
6662 
6663 NK_API void
6664 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
6665 {
6666  nk_buffer_init(&str->buffer, alloc, size);
6667  str->len = 0;
6668 }
6669 
6670 NK_API void
6671 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
6672 {
6673  nk_buffer_init_fixed(&str->buffer, memory, size);
6674  str->len = 0;
6675 }
6676 
6677 NK_API int
6678 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
6679 {
6680  char *mem;
6681  NK_ASSERT(s);
6682  NK_ASSERT(str);
6683  if (!s || !str || !len) return 0;
6684  mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6685  if (!mem) return 0;
6686  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6687  s->len += nk_utf_len(str, len);
6688  return len;
6689 }
6690 
6691 NK_API int
6692 nk_str_append_str_char(struct nk_str *s, const char *str)
6693 {
6694  return nk_str_append_text_char(s, str, nk_strlen(str));
6695 }
6696 
6697 NK_API int
6698 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
6699 {
6700  int i = 0;
6701  int byte_len = 0;
6702  nk_rune unicode;
6703  if (!str || !text || !len) return 0;
6704  for (i = 0; i < len; ++i)
6705  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6706  nk_str_append_text_char(str, text, byte_len);
6707  return len;
6708 }
6709 
6710 NK_API int
6711 nk_str_append_str_utf8(struct nk_str *str, const char *text)
6712 {
6713  int runes = 0;
6714  int byte_len = 0;
6715  int num_runes = 0;
6716  int glyph_len = 0;
6717  nk_rune unicode;
6718  if (!str || !text) return 0;
6719 
6720  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6721  while (unicode != '\0' && glyph_len) {
6722  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6723  byte_len += glyph_len;
6724  num_runes++;
6725  }
6726  nk_str_append_text_char(str, text, byte_len);
6727  return runes;
6728 }
6729 
6730 NK_API int
6731 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
6732 {
6733  int i = 0;
6734  int byte_len = 0;
6735  nk_glyph glyph;
6736 
6737  NK_ASSERT(str);
6738  if (!str || !text || !len) return 0;
6739  for (i = 0; i < len; ++i) {
6740  byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
6741  if (!byte_len) break;
6742  nk_str_append_text_char(str, glyph, byte_len);
6743  }
6744  return len;
6745 }
6746 
6747 NK_API int
6748 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
6749 {
6750  int i = 0;
6751  nk_glyph glyph;
6752  int byte_len;
6753  NK_ASSERT(str);
6754  if (!str || !runes) return 0;
6755  while (runes[i] != '\0') {
6756  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6757  nk_str_append_text_char(str, glyph, byte_len);
6758  i++;
6759  }
6760  return i;
6761 }
6762 
6763 NK_API int
6764 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
6765 {
6766  int i;
6767  void *mem;
6768  char *src;
6769  char *dst;
6770 
6771  int copylen;
6772  NK_ASSERT(s);
6773  NK_ASSERT(str);
6774  NK_ASSERT(len >= 0);
6775  if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
6776  if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
6777  (s->buffer.type == NK_BUFFER_FIXED)) return 0;
6778 
6779  copylen = (int)s->buffer.allocated - pos;
6780  if (!copylen) {
6781  nk_str_append_text_char(s, str, len);
6782  return 1;
6783  }
6784  mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6785  if (!mem) return 0;
6786 
6787  /* memmove */
6788  NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
6789  NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
6790  dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
6791  src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
6792  for (i = 0; i < copylen; ++i) *dst-- = *src--;
6793  mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
6794  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6795  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6796  return 1;
6797 }
6798 
6799 NK_API int
6800 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
6801 {
6802  int glyph_len;
6803  nk_rune unicode;
6804  const char *begin;
6805  const char *buffer;
6806 
6807  NK_ASSERT(str);
6808  NK_ASSERT(cstr);
6809  NK_ASSERT(len);
6810  if (!str || !cstr || !len) return 0;
6811  begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
6812  if (!str->len)
6813  return nk_str_append_text_char(str, cstr, len);
6814  buffer = nk_str_get_const(str);
6815  if (!begin) return 0;
6816  return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
6817 }
6818 
6819 NK_API int
6820 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
6821 {
6822  return nk_str_insert_text_utf8(str, pos, text, len);
6823 }
6824 
6825 NK_API int
6826 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
6827 {
6828  return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
6829 }
6830 
6831 NK_API int
6832 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
6833 {
6834  int i = 0;
6835  int byte_len = 0;
6836  nk_rune unicode;
6837 
6838  NK_ASSERT(str);
6839  NK_ASSERT(text);
6840  if (!str || !text || !len) return 0;
6841  for (i = 0; i < len; ++i)
6842  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6843  nk_str_insert_at_rune(str, pos, text, byte_len);
6844  return len;
6845 }
6846 
6847 NK_API int
6848 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
6849 {
6850  int runes = 0;
6851  int byte_len = 0;
6852  int num_runes = 0;
6853  int glyph_len = 0;
6854  nk_rune unicode;
6855  if (!str || !text) return 0;
6856 
6857  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6858  while (unicode != '\0' && glyph_len) {
6859  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6860  byte_len += glyph_len;
6861  num_runes++;
6862  }
6863  nk_str_insert_at_rune(str, pos, text, byte_len);
6864  return runes;
6865 }
6866 
6867 NK_API int
6868 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
6869 {
6870  int i = 0;
6871  int byte_len = 0;
6872  nk_glyph glyph;
6873 
6874  NK_ASSERT(str);
6875  if (!str || !runes || !len) return 0;
6876  for (i = 0; i < len; ++i) {
6877  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6878  if (!byte_len) break;
6879  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
6880  }
6881  return len;
6882 }
6883 
6884 NK_API int
6885 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
6886 {
6887  int i = 0;
6888  nk_glyph glyph;
6889  int byte_len;
6890  NK_ASSERT(str);
6891  if (!str || !runes) return 0;
6892  while (runes[i] != '\0') {
6893  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6894  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
6895  i++;
6896  }
6897  return i;
6898 }
6899 
6900 NK_API void
6901 nk_str_remove_chars(struct nk_str *s, int len)
6902 {
6903  NK_ASSERT(s);
6904  NK_ASSERT(len >= 0);
6905  if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
6906  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
6907  s->buffer.allocated -= (nk_size)len;
6908  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6909 }
6910 
6911 NK_API void
6912 nk_str_remove_runes(struct nk_str *str, int len)
6913 {
6914  int index;
6915  const char *begin;
6916  const char *end;
6917  nk_rune unicode;
6918 
6919  NK_ASSERT(str);
6920  NK_ASSERT(len >= 0);
6921  if (!str || len < 0) return;
6922  if (len >= str->len) {
6923  str->len = 0;
6924  return;
6925  }
6926 
6927  index = str->len - len;
6928  begin = nk_str_at_rune(str, index, &unicode, &len);
6929  end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
6930  nk_str_remove_chars(str, (int)(end-begin)+1);
6931 }
6932 
6933 NK_API void
6934 nk_str_delete_chars(struct nk_str *s, int pos, int len)
6935 {
6936  NK_ASSERT(s);
6937  if (!s || !len || (nk_size)pos > s->buffer.allocated ||
6938  (nk_size)(pos + len) > s->buffer.allocated) return;
6939 
6940  if ((nk_size)(pos + len) < s->buffer.allocated) {
6941  /* memmove */
6942  char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
6943  char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
6944  NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
6945  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
6946  s->buffer.allocated -= (nk_size)len;
6947  } else nk_str_remove_chars(s, len);
6948  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6949 }
6950 
6951 NK_API void
6952 nk_str_delete_runes(struct nk_str *s, int pos, int len)
6953 {
6954  char *temp;
6955  nk_rune unicode;
6956  char *begin;
6957  char *end;
6958  int unused;
6959 
6960  NK_ASSERT(s);
6961  NK_ASSERT(s->len >= pos + len);
6962  if (s->len < pos + len)
6963  len = NK_CLAMP(0, (s->len - pos), s->len);
6964  if (!len) return;
6965 
6966  temp = (char *)s->buffer.memory.ptr;
6967  begin = nk_str_at_rune(s, pos, &unicode, &unused);
6968  if (!begin) return;
6969  s->buffer.memory.ptr = begin;
6970  end = nk_str_at_rune(s, len, &unicode, &unused);
6971  s->buffer.memory.ptr = temp;
6972  if (!end) return;
6973  nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
6974 }
6975 
6976 NK_API char*
6977 nk_str_at_char(struct nk_str *s, int pos)
6978 {
6979  NK_ASSERT(s);
6980  if (!s || pos > (int)s->buffer.allocated) return 0;
6981  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
6982 }
6983 
6984 NK_API char*
6985 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
6986 {
6987  int i = 0;
6988  int src_len = 0;
6989  int glyph_len = 0;
6990  char *text;
6991  int text_len;
6992 
6993  NK_ASSERT(str);
6994  NK_ASSERT(unicode);
6995  NK_ASSERT(len);
6996 
6997  if (!str || !unicode || !len) return 0;
6998  if (pos < 0) {
6999  *unicode = 0;
7000  *len = 0;
7001  return 0;
7002  }
7003 
7004  text = (char*)str->buffer.memory.ptr;
7005  text_len = (int)str->buffer.allocated;
7006  glyph_len = nk_utf_decode(text, unicode, text_len);
7007  while (glyph_len) {
7008  if (i == pos) {
7009  *len = glyph_len;
7010  break;
7011  }
7012 
7013  i++;
7014  src_len = src_len + glyph_len;
7015  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7016  }
7017  if (i != pos) return 0;
7018  return text + src_len;
7019 }
7020 
7021 NK_API const char*
7022 nk_str_at_char_const(const struct nk_str *s, int pos)
7023 {
7024  NK_ASSERT(s);
7025  if (!s || pos > (int)s->buffer.allocated) return 0;
7026  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
7027 }
7028 
7029 NK_API const char*
7030 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
7031 {
7032  int i = 0;
7033  int src_len = 0;
7034  int glyph_len = 0;
7035  char *text;
7036  int text_len;
7037 
7038  NK_ASSERT(str);
7039  NK_ASSERT(unicode);
7040  NK_ASSERT(len);
7041 
7042  if (!str || !unicode || !len) return 0;
7043  if (pos < 0) {
7044  *unicode = 0;
7045  *len = 0;
7046  return 0;
7047  }
7048 
7049  text = (char*)str->buffer.memory.ptr;
7050  text_len = (int)str->buffer.allocated;
7051  glyph_len = nk_utf_decode(text, unicode, text_len);
7052  while (glyph_len) {
7053  if (i == pos) {
7054  *len = glyph_len;
7055  break;
7056  }
7057 
7058  i++;
7059  src_len = src_len + glyph_len;
7060  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7061  }
7062  if (i != pos) return 0;
7063  return text + src_len;
7064 }
7065 
7066 NK_API nk_rune
7067 nk_str_rune_at(const struct nk_str *str, int pos)
7068 {
7069  int len;
7070  nk_rune unicode = 0;
7071  nk_str_at_const(str, pos, &unicode, &len);
7072  return unicode;
7073 }
7074 
7075 NK_API char*
7076 nk_str_get(struct nk_str *s)
7077 {
7078  NK_ASSERT(s);
7079  if (!s || !s->len || !s->buffer.allocated) return 0;
7080  return (char*)s->buffer.memory.ptr;
7081 }
7082 
7083 NK_API const char*
7084 nk_str_get_const(const struct nk_str *s)
7085 {
7086  NK_ASSERT(s);
7087  if (!s || !s->len || !s->buffer.allocated) return 0;
7088  return (const char*)s->buffer.memory.ptr;
7089 }
7090 
7091 NK_API int
7092 nk_str_len(struct nk_str *s)
7093 {
7094  NK_ASSERT(s);
7095  if (!s || !s->len || !s->buffer.allocated) return 0;
7096  return s->len;
7097 }
7098 
7099 NK_API int
7100 nk_str_len_char(struct nk_str *s)
7101 {
7102  NK_ASSERT(s);
7103  if (!s || !s->len || !s->buffer.allocated) return 0;
7104  return (int)s->buffer.allocated;
7105 }
7106 
7107 NK_API void
7108 nk_str_clear(struct nk_str *str)
7109 {
7110  NK_ASSERT(str);
7111  nk_buffer_clear(&str->buffer);
7112  str->len = 0;
7113 }
7114 
7115 NK_API void
7116 nk_str_free(struct nk_str *str)
7117 {
7118  NK_ASSERT(str);
7119  nk_buffer_free(&str->buffer);
7120  str->len = 0;
7121 }
7122 
7123 /*
7124  * ==============================================================
7125  *
7126  * Command buffer
7127  *
7128  * ===============================================================
7129 */
7130 NK_INTERN void
7131 nk_command_buffer_init(struct nk_command_buffer *cmdbuf,
7132  struct nk_buffer *buffer, enum nk_command_clipping clip)
7133 {
7134  NK_ASSERT(cmdbuf);
7135  NK_ASSERT(buffer);
7136  if (!cmdbuf || !buffer) return;
7137  cmdbuf->base = buffer;
7138  cmdbuf->use_clipping = clip;
7139  cmdbuf->begin = buffer->allocated;
7140  cmdbuf->end = buffer->allocated;
7141  cmdbuf->last = buffer->allocated;
7142 }
7143 
7144 NK_INTERN void
7145 nk_command_buffer_reset(struct nk_command_buffer *buffer)
7146 {
7147  NK_ASSERT(buffer);
7148  if (!buffer) return;
7149  buffer->begin = 0;
7150  buffer->end = 0;
7151  buffer->last = 0;
7152  buffer->clip = nk_null_rect;
7153 #ifdef NK_INCLUDE_COMMAND_USERDATA
7154  buffer->userdata.ptr = 0;
7155 #endif
7156 }
7157 
7158 NK_INTERN void*
7159 nk_command_buffer_push(struct nk_command_buffer* b,
7160  enum nk_command_type t, nk_size size)
7161 {
7162  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
7163  struct nk_command *cmd;
7164  nk_size alignment;
7165  void *unaligned;
7166  void *memory;
7167 
7168  NK_ASSERT(b);
7169  NK_ASSERT(b->base);
7170  if (!b) return 0;
7171  cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
7172  if (!cmd) return 0;
7173 
7174  /* make sure the offset to the next command is aligned */
7175  b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
7176  unaligned = (nk_byte*)cmd + size;
7177  memory = NK_ALIGN_PTR(unaligned, align);
7178  alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
7179 #ifdef NK_ZERO_COMMAND_MEMORY
7180  NK_MEMSET(cmd, 0, size + alignment);
7181 #endif
7182 
7183  cmd->type = t;
7184  cmd->next = b->base->allocated + alignment;
7185 #ifdef NK_INCLUDE_COMMAND_USERDATA
7186  cmd->userdata = b->userdata;
7187 #endif
7188  b->end = cmd->next;
7189  return cmd;
7190 }
7191 
7192 NK_API void
7193 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
7194 {
7195  struct nk_command_scissor *cmd;
7196  NK_ASSERT(b);
7197  if (!b) return;
7198 
7199  b->clip.x = r.x;
7200  b->clip.y = r.y;
7201  b->clip.w = r.w;
7202  b->clip.h = r.h;
7203  cmd = (struct nk_command_scissor*)
7204  nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
7205 
7206  if (!cmd) return;
7207  cmd->x = (short)r.x;
7208  cmd->y = (short)r.y;
7209  cmd->w = (unsigned short)NK_MAX(0, r.w);
7210  cmd->h = (unsigned short)NK_MAX(0, r.h);
7211 }
7212 
7213 NK_API void
7214 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
7215  float x1, float y1, float line_thickness, struct nk_color c)
7216 {
7217  struct nk_command_line *cmd;
7218  NK_ASSERT(b);
7219  if (!b) return;
7220  cmd = (struct nk_command_line*)
7221  nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
7222  if (!cmd) return;
7223  cmd->line_thickness = (unsigned short)line_thickness;
7224  cmd->begin.x = (short)x0;
7225  cmd->begin.y = (short)y0;
7226  cmd->end.x = (short)x1;
7227  cmd->end.y = (short)y1;
7228  cmd->color = c;
7229 }
7230 
7231 NK_API void
7232 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
7233  float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
7234  float bx, float by, float line_thickness, struct nk_color col)
7235 {
7236  struct nk_command_curve *cmd;
7237  NK_ASSERT(b);
7238  if (!b || col.a == 0) return;
7239 
7240  cmd = (struct nk_command_curve*)
7241  nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
7242  if (!cmd) return;
7243  cmd->line_thickness = (unsigned short)line_thickness;
7244  cmd->begin.x = (short)ax;
7245  cmd->begin.y = (short)ay;
7246  cmd->ctrl[0].x = (short)ctrl0x;
7247  cmd->ctrl[0].y = (short)ctrl0y;
7248  cmd->ctrl[1].x = (short)ctrl1x;
7249  cmd->ctrl[1].y = (short)ctrl1y;
7250  cmd->end.x = (short)bx;
7251  cmd->end.y = (short)by;
7252  cmd->color = col;
7253 }
7254 
7255 NK_API void
7256 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
7257  float rounding, float line_thickness, struct nk_color c)
7258 {
7259  struct nk_command_rect *cmd;
7260  NK_ASSERT(b);
7261  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
7262  if (b->use_clipping) {
7263  const struct nk_rect *clip = &b->clip;
7264  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7265  clip->x, clip->y, clip->w, clip->h)) return;
7266  }
7267 
7268  cmd = (struct nk_command_rect*)
7269  nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
7270  if (!cmd) return;
7271  cmd->rounding = (unsigned short)rounding;
7272  cmd->line_thickness = (unsigned short)line_thickness;
7273  cmd->x = (short)rect.x;
7274  cmd->y = (short)rect.y;
7275  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7276  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7277  cmd->color = c;
7278 }
7279 
7280 NK_API void
7281 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
7282  float rounding, struct nk_color c)
7283 {
7284  struct nk_command_rect_filled *cmd;
7285  NK_ASSERT(b);
7286  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
7287  if (b->use_clipping) {
7288  const struct nk_rect *clip = &b->clip;
7289  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7290  clip->x, clip->y, clip->w, clip->h)) return;
7291  }
7292 
7293  cmd = (struct nk_command_rect_filled*)
7294  nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
7295  if (!cmd) return;
7296  cmd->rounding = (unsigned short)rounding;
7297  cmd->x = (short)rect.x;
7298  cmd->y = (short)rect.y;
7299  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7300  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7301  cmd->color = c;
7302 }
7303 
7304 NK_API void
7305 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
7306  struct nk_color left, struct nk_color top, struct nk_color right,
7307  struct nk_color bottom)
7308 {
7309  struct nk_command_rect_multi_color *cmd;
7310  NK_ASSERT(b);
7311  if (!b || rect.w == 0 || rect.h == 0) return;
7312  if (b->use_clipping) {
7313  const struct nk_rect *clip = &b->clip;
7314  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7315  clip->x, clip->y, clip->w, clip->h)) return;
7316  }
7317 
7318  cmd = (struct nk_command_rect_multi_color*)
7319  nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
7320  if (!cmd) return;
7321  cmd->x = (short)rect.x;
7322  cmd->y = (short)rect.y;
7323  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7324  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7325  cmd->left = left;
7326  cmd->top = top;
7327  cmd->right = right;
7328  cmd->bottom = bottom;
7329 }
7330 
7331 NK_API void
7332 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
7333  float line_thickness, struct nk_color c)
7334 {
7335  struct nk_command_circle *cmd;
7336  if (!b || r.w == 0 || r.h == 0) return;
7337  if (b->use_clipping) {
7338  const struct nk_rect *clip = &b->clip;
7339  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7340  return;
7341  }
7342 
7343  cmd = (struct nk_command_circle*)
7344  nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
7345  if (!cmd) return;
7346  cmd->line_thickness = (unsigned short)line_thickness;
7347  cmd->x = (short)r.x;
7348  cmd->y = (short)r.y;
7349  cmd->w = (unsigned short)NK_MAX(r.w, 0);
7350  cmd->h = (unsigned short)NK_MAX(r.h, 0);
7351  cmd->color = c;
7352 }
7353 
7354 NK_API void
7355 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
7356 {
7357  struct nk_command_circle_filled *cmd;
7358  NK_ASSERT(b);
7359  if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
7360  if (b->use_clipping) {
7361  const struct nk_rect *clip = &b->clip;
7362  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7363  return;
7364  }
7365 
7366  cmd = (struct nk_command_circle_filled*)
7367  nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
7368  if (!cmd) return;
7369  cmd->x = (short)r.x;
7370  cmd->y = (short)r.y;
7371  cmd->w = (unsigned short)NK_MAX(r.w, 0);
7372  cmd->h = (unsigned short)NK_MAX(r.h, 0);
7373  cmd->color = c;
7374 }
7375 
7376 NK_API void
7377 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7378  float a_min, float a_max, float line_thickness, struct nk_color c)
7379 {
7380  struct nk_command_arc *cmd;
7381  if (!b || c.a == 0) return;
7382  cmd = (struct nk_command_arc*)
7383  nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
7384  if (!cmd) return;
7385  cmd->line_thickness = (unsigned short)line_thickness;
7386  cmd->cx = (short)cx;
7387  cmd->cy = (short)cy;
7388  cmd->r = (unsigned short)radius;
7389  cmd->a[0] = a_min;
7390  cmd->a[1] = a_max;
7391  cmd->color = c;
7392 }
7393 
7394 NK_API void
7395 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7396  float a_min, float a_max, struct nk_color c)
7397 {
7398  struct nk_command_arc_filled *cmd;
7399  NK_ASSERT(b);
7400  if (!b || c.a == 0) return;
7401  cmd = (struct nk_command_arc_filled*)
7402  nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
7403  if (!cmd) return;
7404  cmd->cx = (short)cx;
7405  cmd->cy = (short)cy;
7406  cmd->r = (unsigned short)radius;
7407  cmd->a[0] = a_min;
7408  cmd->a[1] = a_max;
7409  cmd->color = c;
7410 }
7411 
7412 NK_API void
7413 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7414  float y1, float x2, float y2, float line_thickness, struct nk_color c)
7415 {
7416  struct nk_command_triangle *cmd;
7417  NK_ASSERT(b);
7418  if (!b || c.a == 0) return;
7419  if (b->use_clipping) {
7420  const struct nk_rect *clip = &b->clip;
7421  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7422  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7423  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7424  return;
7425  }
7426 
7427  cmd = (struct nk_command_triangle*)
7428  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
7429  if (!cmd) return;
7430  cmd->line_thickness = (unsigned short)line_thickness;
7431  cmd->a.x = (short)x0;
7432  cmd->a.y = (short)y0;
7433  cmd->b.x = (short)x1;
7434  cmd->b.y = (short)y1;
7435  cmd->c.x = (short)x2;
7436  cmd->c.y = (short)y2;
7437  cmd->color = c;
7438 }
7439 
7440 NK_API void
7441 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7442  float y1, float x2, float y2, struct nk_color c)
7443 {
7444  struct nk_command_triangle_filled *cmd;
7445  NK_ASSERT(b);
7446  if (!b || c.a == 0) return;
7447  if (!b) return;
7448  if (b->use_clipping) {
7449  const struct nk_rect *clip = &b->clip;
7450  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7451  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7452  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7453  return;
7454  }
7455 
7456  cmd = (struct nk_command_triangle_filled*)
7457  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
7458  if (!cmd) return;
7459  cmd->a.x = (short)x0;
7460  cmd->a.y = (short)y0;
7461  cmd->b.x = (short)x1;
7462  cmd->b.y = (short)y1;
7463  cmd->c.x = (short)x2;
7464  cmd->c.y = (short)y2;
7465  cmd->color = c;
7466 }
7467 
7468 NK_API void
7469 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count,
7470  float line_thickness, struct nk_color col)
7471 {
7472  int i;
7473  nk_size size = 0;
7474  struct nk_command_polygon *cmd;
7475 
7476  NK_ASSERT(b);
7477  if (!b || col.a == 0) return;
7478  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7479  cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
7480  if (!cmd) return;
7481  cmd->color = col;
7482  cmd->line_thickness = (unsigned short)line_thickness;
7483  cmd->point_count = (unsigned short)point_count;
7484  for (i = 0; i < point_count; ++i) {
7485  cmd->points[i].x = (short)points[i*2];
7486  cmd->points[i].y = (short)points[i*2+1];
7487  }
7488 }
7489 
7490 NK_API void
7491 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
7492  struct nk_color col)
7493 {
7494  int i;
7495  nk_size size = 0;
7496  struct nk_command_polygon_filled *cmd;
7497 
7498  NK_ASSERT(b);
7499  if (!b || col.a == 0) return;
7500  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7501  cmd = (struct nk_command_polygon_filled*)
7502  nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
7503  if (!cmd) return;
7504  cmd->color = col;
7505  cmd->point_count = (unsigned short)point_count;
7506  for (i = 0; i < point_count; ++i) {
7507  cmd->points[i].x = (short)points[i*2+0];
7508  cmd->points[i].y = (short)points[i*2+1];
7509  }
7510 }
7511 
7512 NK_API void
7513 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count,
7514  float line_thickness, struct nk_color col)
7515 {
7516  int i;
7517  nk_size size = 0;
7518  struct nk_command_polyline *cmd;
7519 
7520  NK_ASSERT(b);
7521  if (!b || col.a == 0) return;
7522  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7523  cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
7524  if (!cmd) return;
7525  cmd->color = col;
7526  cmd->point_count = (unsigned short)point_count;
7527  cmd->line_thickness = (unsigned short)line_thickness;
7528  for (i = 0; i < point_count; ++i) {
7529  cmd->points[i].x = (short)points[i*2];
7530  cmd->points[i].y = (short)points[i*2+1];
7531  }
7532 }
7533 
7534 NK_API void
7535 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
7536  const struct nk_image *img, struct nk_color col)
7537 {
7538  struct nk_command_image *cmd;
7539  NK_ASSERT(b);
7540  if (!b) return;
7541  if (b->use_clipping) {
7542  const struct nk_rect *c = &b->clip;
7543  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7544  return;
7545  }
7546 
7547  cmd = (struct nk_command_image*)
7548  nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
7549  if (!cmd) return;
7550  cmd->x = (short)r.x;
7551  cmd->y = (short)r.y;
7552  cmd->w = (unsigned short)NK_MAX(0, r.w);
7553  cmd->h = (unsigned short)NK_MAX(0, r.h);
7554  cmd->img = *img;
7555  cmd->col = col;
7556 }
7557 
7558 NK_API void
7559 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
7560  nk_command_custom_callback cb, nk_handle usr)
7561 {
7562  struct nk_command_custom *cmd;
7563  NK_ASSERT(b);
7564  if (!b) return;
7565  if (b->use_clipping) {
7566  const struct nk_rect *c = &b->clip;
7567  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7568  return;
7569  }
7570 
7571  cmd = (struct nk_command_custom*)
7572  nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
7573  if (!cmd) return;
7574  cmd->x = (short)r.x;
7575  cmd->y = (short)r.y;
7576  cmd->w = (unsigned short)NK_MAX(0, r.w);
7577  cmd->h = (unsigned short)NK_MAX(0, r.h);
7578  cmd->callback_data = usr;
7579  cmd->callback = cb;
7580 }
7581 
7582 NK_API void
7583 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
7584  const char *string, int length, const struct nk_user_font *font,
7585  struct nk_color bg, struct nk_color fg)
7586 {
7587  float text_width = 0;
7588  struct nk_command_text *cmd;
7589 
7590  NK_ASSERT(b);
7591  NK_ASSERT(font);
7592  if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
7593  if (b->use_clipping) {
7594  const struct nk_rect *c = &b->clip;
7595  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7596  return;
7597  }
7598 
7599  /* make sure text fits inside bounds */
7600  text_width = font->width(font->userdata, font->height, string, length);
7601  if (text_width > r.w){
7602  int glyphs = 0;
7603  float txt_width = (float)text_width;
7604  length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
7605  }
7606 
7607  if (!length) return;
7608  cmd = (struct nk_command_text*)
7609  nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
7610  if (!cmd) return;
7611  cmd->x = (short)r.x;
7612  cmd->y = (short)r.y;
7613  cmd->w = (unsigned short)r.w;
7614  cmd->h = (unsigned short)r.h;
7615  cmd->background = bg;
7616  cmd->foreground = fg;
7617  cmd->font = font;
7618  cmd->length = length;
7619  cmd->height = font->height;
7620  NK_MEMCPY(cmd->string, string, (nk_size)length);
7621  cmd->string[length] = '\0';
7622 }
7623 
7624 /* ==============================================================
7625  *
7626  * DRAW LIST
7627  *
7628  * ===============================================================*/
7629 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
7630 NK_API void
7631 nk_draw_list_init(struct nk_draw_list *list)
7632 {
7633  nk_size i = 0;
7634  NK_ASSERT(list);
7635  if (!list) return;
7636  nk_zero(list, sizeof(*list));
7637  for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
7638  const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
7639  list->circle_vtx[i].x = (float)NK_COS(a);
7640  list->circle_vtx[i].y = (float)NK_SIN(a);
7641  }
7642 }
7643 
7644 NK_API void
7645 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
7646  struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements)
7647 {
7648  NK_ASSERT(canvas);
7649  NK_ASSERT(config);
7650  NK_ASSERT(cmds);
7651  NK_ASSERT(vertices);
7652  NK_ASSERT(elements);
7653  if (!canvas || !config || !cmds || !vertices || !elements)
7654  return;
7655 
7656  canvas->buffer = cmds;
7657  canvas->config = *config;
7658  canvas->elements = elements;
7659  canvas->vertices = vertices;
7660  canvas->clip_rect = nk_null_rect;
7661 }
7662 
7663 NK_API const struct nk_draw_command*
7664 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7665 {
7666  nk_byte *memory;
7667  nk_size offset;
7668  const struct nk_draw_command *cmd;
7669 
7670  NK_ASSERT(buffer);
7671  if (!buffer || !buffer->size || !canvas->cmd_count)
7672  return 0;
7673 
7674  memory = (nk_byte*)buffer->memory.ptr;
7675  offset = buffer->memory.size - canvas->cmd_offset;
7676  cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
7677  return cmd;
7678 }
7679 
7680 NK_API const struct nk_draw_command*
7681 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7682 {
7683  nk_size size;
7684  nk_size offset;
7685  nk_byte *memory;
7686  const struct nk_draw_command *end;
7687 
7688  NK_ASSERT(buffer);
7689  NK_ASSERT(canvas);
7690  if (!buffer || !canvas)
7691  return 0;
7692 
7693  memory = (nk_byte*)buffer->memory.ptr;
7694  size = buffer->memory.size;
7695  offset = size - canvas->cmd_offset;
7696  end = nk_ptr_add(const struct nk_draw_command, memory, offset);
7697  end -= (canvas->cmd_count-1);
7698  return end;
7699 }
7700 
7701 NK_API const struct nk_draw_command*
7702 nk__draw_list_next(const struct nk_draw_command *cmd,
7703  const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
7704 {
7705  const struct nk_draw_command *end;
7706  NK_ASSERT(buffer);
7707  NK_ASSERT(canvas);
7708  if (!cmd || !buffer || !canvas)
7709  return 0;
7710 
7711  end = nk__draw_list_end(canvas, buffer);
7712  if (cmd <= end) return 0;
7713  return (cmd-1);
7714 }
7715 
7716 NK_API void
7717 nk_draw_list_clear(struct nk_draw_list *list)
7718 {
7719  NK_ASSERT(list);
7720  if (!list) return;
7721  if (list->buffer)
7722  nk_buffer_clear(list->buffer);
7723  if (list->vertices)
7724  nk_buffer_clear(list->vertices);
7725  if (list->elements)
7726  nk_buffer_clear(list->elements);
7727 
7728  list->element_count = 0;
7729  list->vertex_count = 0;
7730  list->cmd_offset = 0;
7731  list->cmd_count = 0;
7732  list->path_count = 0;
7733  list->vertices = 0;
7734  list->elements = 0;
7735  list->clip_rect = nk_null_rect;
7736 }
7737 
7738 NK_INTERN struct nk_vec2*
7739 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
7740 {
7741  struct nk_vec2 *points;
7742  NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
7743  NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
7744  points = (struct nk_vec2*)
7745  nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
7746  point_size * (nk_size)count, point_align);
7747 
7748  if (!points) return 0;
7749  if (!list->path_offset) {
7750  void *memory = nk_buffer_memory(list->buffer);
7751  list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
7752  }
7753  list->path_count += (unsigned int)count;
7754  return points;
7755 }
7756 
7757 NK_INTERN struct nk_vec2
7758 nk_draw_list_path_last(struct nk_draw_list *list)
7759 {
7760  void *memory;
7761  struct nk_vec2 *point;
7762  NK_ASSERT(list->path_count);
7763  memory = nk_buffer_memory(list->buffer);
7764  point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
7765  point += (list->path_count-1);
7766  return *point;
7767 }
7768 
7769 NK_INTERN struct nk_draw_command*
7770 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
7771  nk_handle texture)
7772 {
7773  NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
7774  NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
7775  struct nk_draw_command *cmd;
7776 
7777  NK_ASSERT(list);
7778  cmd = (struct nk_draw_command*)
7779  nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
7780 
7781  if (!cmd) return 0;
7782  if (!list->cmd_count) {
7783  nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
7784  nk_size total = nk_buffer_total(list->buffer);
7785  memory = nk_ptr_add(nk_byte, memory, total);
7786  list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
7787  }
7788 
7789  cmd->elem_count = 0;
7790  cmd->clip_rect = clip;
7791  cmd->texture = texture;
7792 #ifdef NK_INCLUDE_COMMAND_USERDATA
7793  cmd->userdata = list->userdata;
7794 #endif
7795 
7796  list->cmd_count++;
7797  list->clip_rect = clip;
7798  return cmd;
7799 }
7800 
7801 NK_INTERN struct nk_draw_command*
7802 nk_draw_list_command_last(struct nk_draw_list *list)
7803 {
7804  void *memory;
7805  nk_size size;
7806  struct nk_draw_command *cmd;
7807  NK_ASSERT(list->cmd_count);
7808 
7809  memory = nk_buffer_memory(list->buffer);
7810  size = nk_buffer_total(list->buffer);
7811  cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
7812  return (cmd - (list->cmd_count-1));
7813 }
7814 
7815 NK_INTERN void
7816 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
7817 {
7818  NK_ASSERT(list);
7819  if (!list) return;
7820  if (!list->cmd_count) {
7821  nk_draw_list_push_command(list, rect, list->config.null.texture);
7822  } else {
7823  struct nk_draw_command *prev = nk_draw_list_command_last(list);
7824  if (prev->elem_count == 0)
7825  prev->clip_rect = rect;
7826  nk_draw_list_push_command(list, rect, prev->texture);
7827  }
7828 }
7829 
7830 NK_INTERN void
7831 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
7832 {
7833  NK_ASSERT(list);
7834  if (!list) return;
7835  if (!list->cmd_count) {
7836  nk_draw_list_push_command(list, nk_null_rect, texture);
7837  } else {
7838  struct nk_draw_command *prev = nk_draw_list_command_last(list);
7839  if (prev->elem_count == 0)
7840  prev->texture = texture;
7841  else if (prev->texture.id != texture.id)
7842  nk_draw_list_push_command(list, prev->clip_rect, texture);
7843  }
7844 }
7845 
7846 #ifdef NK_INCLUDE_COMMAND_USERDATA
7847 NK_API void
7848 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
7849 {
7850  list->userdata = userdata;
7851 }
7852 #endif
7853 
7854 NK_INTERN void*
7855 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
7856 {
7857  void *vtx;
7858  NK_ASSERT(list);
7859  if (!list) return 0;
7860  vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
7861  list->config.vertex_size*count, list->config.vertex_alignment);
7862  if (!vtx) return 0;
7863  list->vertex_count += (unsigned int)count;
7864  return vtx;
7865 }
7866 
7867 NK_INTERN nk_draw_index*
7868 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
7869 {
7870  nk_draw_index *ids;
7871  struct nk_draw_command *cmd;
7872  NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
7873  NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
7874  NK_ASSERT(list);
7875  if (!list) return 0;
7876 
7877  ids = (nk_draw_index*)
7878  nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
7879  if (!ids) return 0;
7880  cmd = nk_draw_list_command_last(list);
7881  list->element_count += (unsigned int)count;
7882  cmd->elem_count += (unsigned int)count;
7883  return ids;
7884 }
7885 
7886 NK_INTERN int
7887 nk_draw_vertex_layout_element_is_end_of_layout(
7888  const struct nk_draw_vertex_layout_element *element)
7889 {
7890  return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
7891  element->format == NK_FORMAT_COUNT);
7892 }
7893 
7894 NK_INTERN void
7895 nk_draw_vertex_color(void *attribute, const float *values,
7896  enum nk_draw_vertex_layout_format format)
7897 {
7898  /* if this triggers you tried to provide a value format for a color */
7899  NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
7900  NK_ASSERT(format <= NK_FORMAT_COLOR_END);
7901  if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
7902 
7903  switch (format) {
7904  default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
7905  case NK_FORMAT_R8G8B8A8:
7906  case NK_FORMAT_R8G8B8: {
7907  struct nk_color col = nk_rgba_fv(values);
7908  NK_MEMCPY(attribute, &col.r, sizeof(col));
7909  } break;
7910  case NK_FORMAT_R16G15B16: {
7911  nk_ushort col[3];
7912  col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
7913  col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
7914  col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
7915  NK_MEMCPY(attribute, col, sizeof(col));
7916  } break;
7917  case NK_FORMAT_R16G15B16A16: {
7918  nk_ushort col[4];
7919  col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
7920  col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
7921  col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
7922  col[3] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[3] * NK_USHORT_MAX, NK_USHORT_MAX);
7923  NK_MEMCPY(attribute, col, sizeof(col));
7924  } break;
7925  case NK_FORMAT_R32G32B32: {
7926  nk_uint col[3];
7927  col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
7928  col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
7929  col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
7930  NK_MEMCPY(attribute, col, sizeof(col));
7931  } break;
7932  case NK_FORMAT_R32G32B32A32: {
7933  nk_uint col[4];
7934  col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
7935  col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
7936  col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
7937  col[3] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[3] * NK_UINT_MAX, NK_UINT_MAX);
7938  NK_MEMCPY(attribute, col, sizeof(col));
7939  } break;
7940  case NK_FORMAT_R32G32B32A32_FLOAT:
7941  NK_MEMCPY(attribute, values, sizeof(float)*4);
7942  break;
7943  case NK_FORMAT_R32G32B32A32_DOUBLE: {
7944  double col[4];
7945  col[0] = (double)NK_SATURATE(values[0]);
7946  col[1] = (double)NK_SATURATE(values[1]);
7947  col[2] = (double)NK_SATURATE(values[2]);
7948  col[3] = (double)NK_SATURATE(values[3]);
7949  NK_MEMCPY(attribute, col, sizeof(col));
7950  } break;
7951  case NK_FORMAT_RGB32:
7952  case NK_FORMAT_RGBA32: {
7953  struct nk_color col = nk_rgba_fv(values);
7954  nk_uint color = nk_color_u32(col);
7955  NK_MEMCPY(attribute, &color, sizeof(color));
7956  } break;
7957  }
7958 }
7959 
7960 NK_INTERN void
7961 nk_draw_vertex_element(void *dst, const float *values, int value_count,
7962  enum nk_draw_vertex_layout_format format)
7963 {
7964  int value_index;
7965  void *attribute = dst;
7966  /* if this triggers you tried to provide a color format for a value */
7967  NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
7968  if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
7969  for (value_index = 0; value_index < value_count; ++value_index) {
7970  switch (format) {
7971  default: NK_ASSERT(0 && "invalid vertex layout format"); break;
7972  case NK_FORMAT_SCHAR: {
7973  char value = (char)NK_CLAMP(NK_SCHAR_MIN, values[value_index], NK_SCHAR_MAX);
7974  NK_MEMCPY(attribute, &value, sizeof(value));
7975  attribute = (void*)((char*)attribute + sizeof(char));
7976  } break;
7977  case NK_FORMAT_SSHORT: {
7978  nk_short value = (nk_short)NK_CLAMP(NK_SSHORT_MIN, values[value_index], NK_SSHORT_MAX);
7979  NK_MEMCPY(attribute, &value, sizeof(value));
7980  attribute = (void*)((char*)attribute + sizeof(value));
7981  } break;
7982  case NK_FORMAT_SINT: {
7983  nk_int value = (nk_int)NK_CLAMP(NK_SINT_MIN, values[value_index], NK_SINT_MAX);
7984  NK_MEMCPY(attribute, &value, sizeof(value));
7985  attribute = (void*)((char*)attribute + sizeof(nk_int));
7986  } break;
7987  case NK_FORMAT_UCHAR: {
7988  unsigned char value = (unsigned char)NK_CLAMP(NK_UCHAR_MIN, values[value_index], NK_UCHAR_MAX);
7989  NK_MEMCPY(attribute, &value, sizeof(value));
7990  attribute = (void*)((char*)attribute + sizeof(unsigned char));
7991  } break;
7992  case NK_FORMAT_USHORT: {
7993  nk_ushort value = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[value_index], NK_USHORT_MAX);
7994  NK_MEMCPY(attribute, &value, sizeof(value));
7995  attribute = (void*)((char*)attribute + sizeof(value));
7996  } break;
7997  case NK_FORMAT_UINT: {
7998  nk_uint value = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[value_index], NK_UINT_MAX);
7999  NK_MEMCPY(attribute, &value, sizeof(value));
8000  attribute = (void*)((char*)attribute + sizeof(nk_uint));
8001  } break;
8002  case NK_FORMAT_FLOAT:
8003  NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
8004  attribute = (void*)((char*)attribute + sizeof(float));
8005  break;
8006  case NK_FORMAT_DOUBLE: {
8007  double value = (double)values[value_index];
8008  NK_MEMCPY(attribute, &value, sizeof(value));
8009  attribute = (void*)((char*)attribute + sizeof(double));
8010  } break;
8011  }
8012  }
8013 }
8014 
8015 NK_INTERN void*
8016 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
8017  struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
8018 {
8019  void *result = (void*)((char*)dst + config->vertex_size);
8020  const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
8021  while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
8022  void *address = (void*)((char*)dst + elem_iter->offset);
8023  switch (elem_iter->attribute) {
8024  case NK_VERTEX_ATTRIBUTE_COUNT:
8025  default: NK_ASSERT(0 && "wrong element attribute");
8026  case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
8027  case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
8028  case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
8029  }
8030  elem_iter++;
8031  }
8032  return result;
8033 }
8034 
8035 NK_API void
8036 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
8037  const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
8038  float thickness, enum nk_anti_aliasing aliasing)
8039 {
8040  nk_size count;
8041  int thick_line;
8042  struct nk_colorf col;
8043  struct nk_colorf col_trans;
8044  NK_ASSERT(list);
8045  if (!list || points_count < 2) return;
8046 
8047  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8048  count = points_count;
8049  if (!closed) count = points_count-1;
8050  thick_line = thickness > 1.0f;
8051 
8052 #ifdef NK_INCLUDE_COMMAND_USERDATA
8053  nk_draw_list_push_userdata(list, list->userdata);
8054 #endif
8055 
8056  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8057  nk_color_fv(&col.r, color);
8058  col_trans = col;
8059  col_trans.a = 0;
8060 
8061  if (aliasing == NK_ANTI_ALIASING_ON) {
8062  /* ANTI-ALIASED STROKE */
8063  const float AA_SIZE = 1.0f;
8064  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8065  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8066 
8067  /* allocate vertices and elements */
8068  nk_size i1 = 0;
8069  nk_size vertex_offset;
8070  nk_size index = list->vertex_count;
8071 
8072  const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12);
8073  const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
8074 
8075  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8076  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8077 
8078  nk_size size;
8079  struct nk_vec2 *normals, *temp;
8080  if (!vtx || !ids) return;
8081 
8082  /* temporary allocate normals + points */
8083  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8084  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8085  size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
8086  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8087  NK_ASSERT(normals);
8088  if (!normals) return;
8089  temp = normals + points_count;
8090 
8091  /* make sure vertex pointer is still correct */
8092  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8093 
8094  /* calculate normals */
8095  for (i1 = 0; i1 < count; ++i1) {
8096  const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8097  struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
8098  float len;
8099 
8100  /* vec2 inverted length */
8101  len = nk_vec2_len_sqr(diff);
8102  if (len != 0.0f)
8103  len = nk_inv_sqrt(len);
8104  else len = 1.0f;
8105 
8106  diff = nk_vec2_muls(diff, len);
8107  normals[i1].x = diff.y;
8108  normals[i1].y = -diff.x;
8109  }
8110 
8111  if (!closed)
8112  normals[points_count-1] = normals[points_count-2];
8113 
8114  if (!thick_line) {
8115  nk_size idx1, i;
8116  if (!closed) {
8117  struct nk_vec2 d;
8118  temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8119  temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8120  d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
8121  temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
8122  temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
8123  }
8124 
8125  /* fill elements */
8126  idx1 = index;
8127  for (i1 = 0; i1 < count; i1++) {
8128  struct nk_vec2 dm;
8129  float dmr2;
8130  nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8131  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
8132 
8133  /* average normals */
8134  dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8135  dmr2 = dm.x * dm.x + dm.y* dm.y;
8136  if (dmr2 > 0.000001f) {
8137  float scale = 1.0f/dmr2;
8138  scale = NK_MIN(100.0f, scale);
8139  dm = nk_vec2_muls(dm, scale);
8140  }
8141 
8142  dm = nk_vec2_muls(dm, AA_SIZE);
8143  temp[i2*2+0] = nk_vec2_add(points[i2], dm);
8144  temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
8145 
8146  ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
8147  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8148  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
8149  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8150  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8151  ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
8152  ids += 12;
8153  idx1 = idx2;
8154  }
8155 
8156  /* fill vertices */
8157  for (i = 0; i < points_count; ++i) {
8158  const struct nk_vec2 uv = list->config.null.uv;
8159  vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
8160  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
8161  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
8162  }
8163  } else {
8164  nk_size idx1, i;
8165  const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
8166  if (!closed) {
8167  struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
8168  struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
8169 
8170  temp[0] = nk_vec2_add(points[0], d1);
8171  temp[1] = nk_vec2_add(points[0], d2);
8172  temp[2] = nk_vec2_sub(points[0], d2);
8173  temp[3] = nk_vec2_sub(points[0], d1);
8174 
8175  d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
8176  d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
8177 
8178  temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
8179  temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
8180  temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
8181  temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
8182  }
8183 
8184  /* add all elements */
8185  idx1 = index;
8186  for (i1 = 0; i1 < count; ++i1) {
8187  struct nk_vec2 dm_out, dm_in;
8188  const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
8189  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
8190 
8191  /* average normals */
8192  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8193  float dmr2 = dm.x * dm.x + dm.y* dm.y;
8194  if (dmr2 > 0.000001f) {
8195  float scale = 1.0f/dmr2;
8196  scale = NK_MIN(100.0f, scale);
8197  dm = nk_vec2_muls(dm, scale);
8198  }
8199 
8200  dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
8201  dm_in = nk_vec2_muls(dm, half_inner_thickness);
8202  temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
8203  temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
8204  temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
8205  temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
8206 
8207  /* add indexes */
8208  ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
8209  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8210  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
8211  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8212  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8213  ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
8214  ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
8215  ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
8216  ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
8217  ids += 18;
8218  idx1 = idx2;
8219  }
8220 
8221  /* add vertices */
8222  for (i = 0; i < points_count; ++i) {
8223  const struct nk_vec2 uv = list->config.null.uv;
8224  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
8225  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
8226  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
8227  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
8228  }
8229  }
8230  /* free temporary normals + points */
8231  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8232  } else {
8233  /* NON ANTI-ALIASED STROKE */
8234  nk_size i1 = 0;
8235  nk_size idx = list->vertex_count;
8236  const nk_size idx_count = count * 6;
8237  const nk_size vtx_count = count * 4;
8238  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8239  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8240  if (!vtx || !ids) return;
8241 
8242  for (i1 = 0; i1 < count; ++i1) {
8243  float dx, dy;
8244  const struct nk_vec2 uv = list->config.null.uv;
8245  const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
8246  const struct nk_vec2 p1 = points[i1];
8247  const struct nk_vec2 p2 = points[i2];
8248  struct nk_vec2 diff = nk_vec2_sub(p2, p1);
8249  float len;
8250 
8251  /* vec2 inverted length */
8252  len = nk_vec2_len_sqr(diff);
8253  if (len != 0.0f)
8254  len = nk_inv_sqrt(len);
8255  else len = 1.0f;
8256  diff = nk_vec2_muls(diff, len);
8257 
8258  /* add vertices */
8259  dx = diff.x * (thickness * 0.5f);
8260  dy = diff.y * (thickness * 0.5f);
8261 
8262  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
8263  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
8264  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
8265  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
8266 
8267  ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
8268  ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
8269  ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
8270 
8271  ids += 6;
8272  idx += 4;
8273  }
8274  }
8275 }
8276 
8277 NK_API void
8278 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
8279  const struct nk_vec2 *points, const unsigned int points_count,
8280  struct nk_color color, enum nk_anti_aliasing aliasing)
8281 {
8282  struct nk_colorf col;
8283  struct nk_colorf col_trans;
8284 
8285  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8286  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8287  NK_ASSERT(list);
8288  if (!list || points_count < 3) return;
8289 
8290 #ifdef NK_INCLUDE_COMMAND_USERDATA
8291  nk_draw_list_push_userdata(list, list->userdata);
8292 #endif
8293 
8294  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8295  nk_color_fv(&col.r, color);
8296  col_trans = col;
8297  col_trans.a = 0;
8298 
8299  if (aliasing == NK_ANTI_ALIASING_ON) {
8300  nk_size i = 0;
8301  nk_size i0 = 0;
8302  nk_size i1 = 0;
8303 
8304  const float AA_SIZE = 1.0f;
8305  nk_size vertex_offset = 0;
8306  nk_size index = list->vertex_count;
8307 
8308  const nk_size idx_count = (points_count-2)*3 + points_count*6;
8309  const nk_size vtx_count = (points_count*2);
8310 
8311  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8312  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8313 
8314  nk_size size = 0;
8315  struct nk_vec2 *normals = 0;
8316  unsigned int vtx_inner_idx = (unsigned int)(index + 0);
8317  unsigned int vtx_outer_idx = (unsigned int)(index + 1);
8318  if (!vtx || !ids) return;
8319 
8320  /* temporary allocate normals */
8321  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8322  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8323  size = pnt_size * points_count;
8324  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8325  NK_ASSERT(normals);
8326  if (!normals) return;
8327  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8328 
8329  /* add elements */
8330  for (i = 2; i < points_count; i++) {
8331  ids[0] = (nk_draw_index)(vtx_inner_idx);
8332  ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
8333  ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
8334  ids += 3;
8335  }
8336 
8337  /* compute normals */
8338  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8339  struct nk_vec2 p0 = points[i0];
8340  struct nk_vec2 p1 = points[i1];
8341  struct nk_vec2 diff = nk_vec2_sub(p1, p0);
8342 
8343  /* vec2 inverted length */
8344  float len = nk_vec2_len_sqr(diff);
8345  if (len != 0.0f)
8346  len = nk_inv_sqrt(len);
8347  else len = 1.0f;
8348  diff = nk_vec2_muls(diff, len);
8349 
8350  normals[i0].x = diff.y;
8351  normals[i0].y = -diff.x;
8352  }
8353 
8354  /* add vertices + indexes */
8355  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8356  const struct nk_vec2 uv = list->config.null.uv;
8357  struct nk_vec2 n0 = normals[i0];
8358  struct nk_vec2 n1 = normals[i1];
8359  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
8360  float dmr2 = dm.x*dm.x + dm.y*dm.y;
8361  if (dmr2 > 0.000001f) {
8362  float scale = 1.0f / dmr2;
8363  scale = NK_MIN(scale, 100.0f);
8364  dm = nk_vec2_muls(dm, scale);
8365  }
8366  dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
8367 
8368  /* add vertices */
8369  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
8370  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
8371 
8372  /* add indexes */
8373  ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8374  ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
8375  ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8376  ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8377  ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
8378  ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8379  ids += 6;
8380  }
8381  /* free temporary normals + points */
8382  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8383  } else {
8384  nk_size i = 0;
8385  nk_size index = list->vertex_count;
8386  const nk_size idx_count = (points_count-2)*3;
8387  const nk_size vtx_count = points_count;
8388  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8389  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8390 
8391  if (!vtx || !ids) return;
8392  for (i = 0; i < vtx_count; ++i)
8393  vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
8394  for (i = 2; i < points_count; ++i) {
8395  ids[0] = (nk_draw_index)index;
8396  ids[1] = (nk_draw_index)(index+ i - 1);
8397  ids[2] = (nk_draw_index)(index+i);
8398  ids += 3;
8399  }
8400  }
8401 }
8402 
8403 NK_API void
8404 nk_draw_list_path_clear(struct nk_draw_list *list)
8405 {
8406  NK_ASSERT(list);
8407  if (!list) return;
8408  nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
8409  list->path_count = 0;
8410  list->path_offset = 0;
8411 }
8412 
8413 NK_API void
8414 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
8415 {
8416  struct nk_vec2 *points = 0;
8417  struct nk_draw_command *cmd = 0;
8418  NK_ASSERT(list);
8419  if (!list) return;
8420  if (!list->cmd_count)
8421  nk_draw_list_add_clip(list, nk_null_rect);
8422 
8423  cmd = nk_draw_list_command_last(list);
8424  if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
8425  nk_draw_list_push_image(list, list->config.null.texture);
8426 
8427  points = nk_draw_list_alloc_path(list, 1);
8428  if (!points) return;
8429  points[0] = pos;
8430 }
8431 
8432 NK_API void
8433 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
8434  float radius, int a_min, int a_max)
8435 {
8436  int a = 0;
8437  NK_ASSERT(list);
8438  if (!list) return;
8439  if (a_min <= a_max) {
8440  for (a = a_min; a <= a_max; a++) {
8441  const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
8442  const float x = center.x + c.x * radius;
8443  const float y = center.y + c.y * radius;
8444  nk_draw_list_path_line_to(list, nk_vec2(x, y));
8445  }
8446  }
8447 }
8448 
8449 NK_API void
8450 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
8451  float radius, float a_min, float a_max, unsigned int segments)
8452 {
8453  unsigned int i = 0;
8454  NK_ASSERT(list);
8455  if (!list) return;
8456  if (radius == 0.0f) return;
8457  for (i = 0; i <= segments; ++i) {
8458  const float a = a_min + ((float)i / ((float)segments) * (a_max - a_min));
8459  const float x = center.x + (float)NK_COS(a) * radius;
8460  const float y = center.y + (float)NK_SIN(a) * radius;
8461  nk_draw_list_path_line_to(list, nk_vec2(x, y));
8462  }
8463 }
8464 
8465 NK_API void
8466 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
8467  struct nk_vec2 b, float rounding)
8468 {
8469  float r;
8470  NK_ASSERT(list);
8471  if (!list) return;
8472  r = rounding;
8473  r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
8474  r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
8475 
8476  if (r == 0.0f) {
8477  nk_draw_list_path_line_to(list, a);
8478  nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
8479  nk_draw_list_path_line_to(list, b);
8480  nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
8481  } else {
8482  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
8483  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
8484  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
8485  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
8486  }
8487 }
8488 
8489 NK_API void
8490 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
8491  struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
8492 {
8493  float t_step;
8494  unsigned int i_step;
8495  struct nk_vec2 p1;
8496 
8497  NK_ASSERT(list);
8498  NK_ASSERT(list->path_count);
8499  if (!list || !list->path_count) return;
8500  num_segments = NK_MAX(num_segments, 1);
8501 
8502  p1 = nk_draw_list_path_last(list);
8503  t_step = 1.0f/(float)num_segments;
8504  for (i_step = 1; i_step <= num_segments; ++i_step) {
8505  float t = t_step * (float)i_step;
8506  float u = 1.0f - t;
8507  float w1 = u*u*u;
8508  float w2 = 3*u*u*t;
8509  float w3 = 3*u*t*t;
8510  float w4 = t * t *t;
8511  float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
8512  float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
8513  nk_draw_list_path_line_to(list, nk_vec2(x,y));
8514  }
8515 }
8516 
8517 NK_API void
8518 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
8519 {
8520  struct nk_vec2 *points;
8521  NK_ASSERT(list);
8522  if (!list) return;
8523  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8524  nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
8525  nk_draw_list_path_clear(list);
8526 }
8527 
8528 NK_API void
8529 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
8530  enum nk_draw_list_stroke closed, float thickness)
8531 {
8532  struct nk_vec2 *points;
8533  NK_ASSERT(list);
8534  if (!list) return;
8535  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8536  nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
8537  closed, thickness, list->config.line_AA);
8538  nk_draw_list_path_clear(list);
8539 }
8540 
8541 NK_API void
8542 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
8543  struct nk_vec2 b, struct nk_color col, float thickness)
8544 {
8545  NK_ASSERT(list);
8546  if (!list || !col.a) return;
8547  nk_draw_list_path_line_to(list, nk_vec2_add(a, nk_vec2(0.5f, 0.5f)));
8548  nk_draw_list_path_line_to(list, nk_vec2_add(b, nk_vec2(0.5f, 0.5f)));
8549  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8550 }
8551 
8552 NK_API void
8553 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
8554  struct nk_color col, float rounding)
8555 {
8556  NK_ASSERT(list);
8557  if (!list || !col.a) return;
8558  nk_draw_list_path_rect_to(list, nk_vec2(rect.x + 0.5f, rect.y + 0.5f),
8559  nk_vec2(rect.x + rect.w + 0.5f, rect.y + rect.h + 0.5f), rounding);
8560  nk_draw_list_path_fill(list, col);
8561 }
8562 
8563 NK_API void
8564 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
8565  struct nk_color col, float rounding, float thickness)
8566 {
8567  NK_ASSERT(list);
8568  if (!list || !col.a) return;
8569  nk_draw_list_path_rect_to(list, nk_vec2(rect.x + 0.5f, rect.y + 0.5f),
8570  nk_vec2(rect.x + rect.w + 0.5f, rect.y + rect.h + 0.5f), rounding);
8571  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8572 }
8573 
8574 NK_API void
8575 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
8576  struct nk_color left, struct nk_color top, struct nk_color right,
8577  struct nk_color bottom)
8578 {
8579  void *vtx;
8580  struct nk_colorf col_left, col_top;
8581  struct nk_colorf col_right, col_bottom;
8582  nk_draw_index *idx;
8583  nk_draw_index index;
8584 
8585  nk_color_fv(&col_left.r, left);
8586  nk_color_fv(&col_right.r, right);
8587  nk_color_fv(&col_top.r, top);
8588  nk_color_fv(&col_bottom.r, bottom);
8589 
8590  NK_ASSERT(list);
8591  if (!list) return;
8592 
8593  nk_draw_list_push_image(list, list->config.null.texture);
8594  index = (nk_draw_index)list->vertex_count;
8595  vtx = nk_draw_list_alloc_vertices(list, 4);
8596  idx = nk_draw_list_alloc_elements(list, 6);
8597  if (!vtx || !idx) return;
8598 
8599  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8600  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8601  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8602 
8603  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
8604  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
8605  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
8606  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
8607 }
8608 
8609 NK_API void
8610 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8611  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
8612 {
8613  NK_ASSERT(list);
8614  if (!list || !col.a) return;
8615  nk_draw_list_path_line_to(list, a);
8616  nk_draw_list_path_line_to(list, b);
8617  nk_draw_list_path_line_to(list, c);
8618  nk_draw_list_path_fill(list, col);
8619 }
8620 
8621 NK_API void
8622 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8623  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
8624 {
8625  NK_ASSERT(list);
8626  if (!list || !col.a) return;
8627  nk_draw_list_path_line_to(list, a);
8628  nk_draw_list_path_line_to(list, b);
8629  nk_draw_list_path_line_to(list, c);
8630  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8631 }
8632 
8633 NK_API void
8634 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
8635  float radius, struct nk_color col, unsigned int segs)
8636 {
8637  float a_max;
8638  NK_ASSERT(list);
8639  if (!list || !col.a) return;
8640  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8641  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8642  nk_draw_list_path_fill(list, col);
8643 }
8644 
8645 NK_API void
8646 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
8647  float radius, struct nk_color col, unsigned int segs, float thickness)
8648 {
8649  float a_max;
8650  NK_ASSERT(list);
8651  if (!list || !col.a) return;
8652  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8653  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8654  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8655 }
8656 
8657 NK_API void
8658 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
8659  struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
8660  struct nk_color col, unsigned int segments, float thickness)
8661 {
8662  NK_ASSERT(list);
8663  if (!list || !col.a) return;
8664  nk_draw_list_path_line_to(list, p0);
8665  nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
8666  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8667 }
8668 
8669 NK_INTERN void
8670 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
8671  struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
8672  struct nk_color color)
8673 {
8674  void *vtx;
8675  struct nk_vec2 uvb;
8676  struct nk_vec2 uvd;
8677  struct nk_vec2 b;
8678  struct nk_vec2 d;
8679 
8680  struct nk_colorf col;
8681  nk_draw_index *idx;
8682  nk_draw_index index;
8683  NK_ASSERT(list);
8684  if (!list) return;
8685 
8686  nk_color_fv(&col.r, color);
8687  uvb = nk_vec2(uvc.x, uva.y);
8688  uvd = nk_vec2(uva.x, uvc.y);
8689  b = nk_vec2(c.x, a.y);
8690  d = nk_vec2(a.x, c.y);
8691 
8692  index = (nk_draw_index)list->vertex_count;
8693  vtx = nk_draw_list_alloc_vertices(list, 4);
8694  idx = nk_draw_list_alloc_elements(list, 6);
8695  if (!vtx || !idx) return;
8696 
8697  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8698  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8699  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8700 
8701  vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
8702  vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
8703  vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
8704  vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
8705 }
8706 
8707 NK_API void
8708 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
8709  struct nk_rect rect, struct nk_color color)
8710 {
8711  NK_ASSERT(list);
8712  if (!list) return;
8713  /* push new command with given texture */
8714  nk_draw_list_push_image(list, texture.handle);
8715  if (nk_image_is_subimage(&texture)) {
8716  /* add region inside of the texture */
8717  struct nk_vec2 uv[2];
8718  uv[0].x = (float)texture.region[0]/(float)texture.w;
8719  uv[0].y = (float)texture.region[1]/(float)texture.h;
8720  uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
8721  uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
8722  nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8723  nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color);
8724  } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8725  nk_vec2(rect.x + rect.w, rect.y + rect.h),
8726  nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
8727 }
8728 
8729 NK_API void
8730 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
8731  struct nk_rect rect, const char *text, int len, float font_height,
8732  struct nk_color fg)
8733 {
8734  float x = 0;
8735  int text_len = 0;
8736  nk_rune unicode = 0;
8737  nk_rune next = 0;
8738  int glyph_len = 0;
8739  int next_glyph_len = 0;
8740  struct nk_user_font_glyph g;
8741 
8742  NK_ASSERT(list);
8743  if (!list || !len || !text) return;
8744  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8745  list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
8746 
8747  nk_draw_list_push_image(list, font->texture);
8748  x = rect.x;
8749  glyph_len = nk_utf_decode(text, &unicode, len);
8750  if (!glyph_len) return;
8751 
8752  /* draw every glyph image */
8753  fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
8754  while (text_len < len && glyph_len) {
8755  float gx, gy, gh, gw;
8756  float char_width = 0;
8757  if (unicode == NK_UTF_INVALID) break;
8758 
8759  /* query currently drawn glyph information */
8760  next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
8761  font->query(font->userdata, font_height, &g, unicode,
8762  (next == NK_UTF_INVALID) ? '\0' : next);
8763 
8764  /* calculate and draw glyph drawing rectangle and image */
8765  gx = x + g.offset.x;
8766  gy = rect.y + g.offset.y;
8767  gw = g.width; gh = g.height;
8768  char_width = g.xadvance;
8769  nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
8770  g.uv[0], g.uv[1], fg);
8771 
8772  /* offset next glyph */
8773  text_len += glyph_len;
8774  x += char_width;
8775  glyph_len = next_glyph_len;
8776  unicode = next;
8777  }
8778 }
8779 
8780 NK_API nk_flags
8781 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
8782  struct nk_buffer *vertices, struct nk_buffer *elements,
8783  const struct nk_convert_config *config)
8784 {
8785  nk_flags res = NK_CONVERT_SUCCESS;
8786  const struct nk_command *cmd;
8787  NK_ASSERT(ctx);
8788  NK_ASSERT(cmds);
8789  NK_ASSERT(vertices);
8790  NK_ASSERT(elements);
8791  NK_ASSERT(config);
8792  NK_ASSERT(config->vertex_layout);
8793  NK_ASSERT(config->vertex_size);
8794  if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
8795  return NK_CONVERT_INVALID_PARAM;
8796 
8797  nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements);
8798  nk_foreach(cmd, ctx)
8799  {
8800 #ifdef NK_INCLUDE_COMMAND_USERDATA
8801  ctx->draw_list.userdata = cmd->userdata;
8802 #endif
8803  switch (cmd->type) {
8804  case NK_COMMAND_NOP: break;
8805  case NK_COMMAND_SCISSOR: {
8806  const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
8807  nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
8808  } break;
8809  case NK_COMMAND_LINE: {
8810  const struct nk_command_line *l = (const struct nk_command_line*)cmd;
8811  nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
8812  nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
8813  } break;
8814  case NK_COMMAND_CURVE: {
8815  const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
8816  nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
8817  nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
8818  q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
8819  config->curve_segment_count, q->line_thickness);
8820  } break;
8821  case NK_COMMAND_RECT: {
8822  const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
8823  nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
8824  r->color, (float)r->rounding, r->line_thickness);
8825  } break;
8826  case NK_COMMAND_RECT_FILLED: {
8827  const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
8828  nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
8829  r->color, (float)r->rounding);
8830  } break;
8832  const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
8833  nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
8834  r->left, r->top, r->right, r->bottom);
8835  } break;
8836  case NK_COMMAND_CIRCLE: {
8837  const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
8838  nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
8839  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
8840  config->circle_segment_count, c->line_thickness);
8841  } break;
8842  case NK_COMMAND_CIRCLE_FILLED: {
8843  const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
8844  nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
8845  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
8846  config->circle_segment_count);
8847  } break;
8848  case NK_COMMAND_ARC: {
8849  const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
8850  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
8851  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
8852  c->a[0], c->a[1], config->arc_segment_count);
8853  nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
8854  } break;
8855  case NK_COMMAND_ARC_FILLED: {
8856  const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
8857  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
8858  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
8859  c->a[0], c->a[1], config->arc_segment_count);
8860  nk_draw_list_path_fill(&ctx->draw_list, c->color);
8861  } break;
8862  case NK_COMMAND_TRIANGLE: {
8863  const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
8864  nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
8865  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
8866  t->line_thickness);
8867  } break;
8869  const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
8870  nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
8871  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
8872  } break;
8873  case NK_COMMAND_POLYGON: {
8874  int i;
8875  const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
8876  for (i = 0; i < p->point_count; ++i) {
8877  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
8878  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
8879  }
8880  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
8881  } break;
8883  int i;
8884  const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
8885  for (i = 0; i < p->point_count; ++i) {
8886  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
8887  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
8888  }
8889  nk_draw_list_path_fill(&ctx->draw_list, p->color);
8890  } break;
8891  case NK_COMMAND_POLYLINE: {
8892  int i;
8893  const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
8894  for (i = 0; i < p->point_count; ++i) {
8895  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
8896  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
8897  }
8898  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
8899  } break;
8900  case NK_COMMAND_TEXT: {
8901  const struct nk_command_text *t = (const struct nk_command_text*)cmd;
8902  nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
8903  t->string, t->length, t->height, t->foreground);
8904  } break;
8905  case NK_COMMAND_IMAGE: {
8906  const struct nk_command_image *i = (const struct nk_command_image*)cmd;
8907  nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
8908  } break;
8909  case NK_COMMAND_CUSTOM: {
8910  const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
8911  c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
8912  } break;
8913  default: break;
8914  }
8915  }
8916  res |= (cmds->needed > cmds->allocated) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
8917  res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
8918  res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
8919  return res;
8920 }
8921 NK_API const struct nk_draw_command*
8922 nk__draw_begin(const struct nk_context *ctx,
8923  const struct nk_buffer *buffer)
8924 {return nk__draw_list_begin(&ctx->draw_list, buffer);}
8925 
8926 NK_API const struct nk_draw_command*
8927 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
8928 {return nk__draw_list_end(&ctx->draw_list, buffer);}
8929 
8930 NK_API const struct nk_draw_command*
8931 nk__draw_next(const struct nk_draw_command *cmd,
8932  const struct nk_buffer *buffer, const struct nk_context *ctx)
8933 {return nk__draw_list_next(cmd, buffer, &ctx->draw_list);}
8934 
8935 #endif
8936 
8937 /*
8938  * ==============================================================
8939  *
8940  * FONT HANDLING
8941  *
8942  * ===============================================================
8943  */
8944 #ifdef NK_INCLUDE_FONT_BAKING
8945 /* -------------------------------------------------------------
8946  *
8947  * RECT PACK
8948  *
8949  * --------------------------------------------------------------*/
8950 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
8951 /* Sean Barrett 2014 */
8952 #define NK_RP__MAXVAL 0xffff
8953 typedef unsigned short nk_rp_coord;
8954 
8955 struct nk_rp_rect {
8956  /* reserved for your use: */
8957  int id;
8958  /* input: */
8959  nk_rp_coord w, h;
8960  /* output: */
8961  nk_rp_coord x, y;
8962  int was_packed;
8963  /* non-zero if valid packing */
8964 }; /* 16 bytes, nominally */
8965 
8966 struct nk_rp_node {
8967  nk_rp_coord x,y;
8968  struct nk_rp_node *next;
8969 };
8970 
8971 struct nk_rp_context {
8972  int width;
8973  int height;
8974  int align;
8975  int init_mode;
8976  int heuristic;
8977  int num_nodes;
8978  struct nk_rp_node *active_head;
8979  struct nk_rp_node *free_head;
8980  struct nk_rp_node extra[2];
8981  /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
8982 };
8983 
8984 struct nk_rp__findresult {
8985  int x,y;
8986  struct nk_rp_node **prev_link;
8987 };
8988 
8989 enum NK_RP_HEURISTIC {
8990  NK_RP_HEURISTIC_Skyline_default=0,
8991  NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
8992  NK_RP_HEURISTIC_Skyline_BF_sortHeight
8993 };
8994 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
8995 
8996 NK_INTERN void
8997 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
8998 {
8999  if (allow_out_of_mem)
9000  /* if it's ok to run out of memory, then don't bother aligning them; */
9001  /* this gives better packing, but may fail due to OOM (even though */
9002  /* the rectangles easily fit). @TODO a smarter approach would be to only */
9003  /* quantize once we've hit OOM, then we could get rid of this parameter. */
9004  context->align = 1;
9005  else {
9006  /* if it's not ok to run out of memory, then quantize the widths */
9007  /* so that num_nodes is always enough nodes. */
9008  /* */
9009  /* I.e. num_nodes * align >= width */
9010  /* align >= width / num_nodes */
9011  /* align = ceil(width/num_nodes) */
9012  context->align = (context->width + context->num_nodes-1) / context->num_nodes;
9013  }
9014 }
9015 
9016 NK_INTERN void
9017 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
9018  struct nk_rp_node *nodes, int num_nodes)
9019 {
9020  int i;
9021 #ifndef STBRP_LARGE_RECTS
9022  NK_ASSERT(width <= 0xffff && height <= 0xffff);
9023 #endif
9024 
9025  for (i=0; i < num_nodes-1; ++i)
9026  nodes[i].next = &nodes[i+1];
9027  nodes[i].next = 0;
9028  context->init_mode = NK_RP__INIT_skyline;
9029  context->heuristic = NK_RP_HEURISTIC_Skyline_default;
9030  context->free_head = &nodes[0];
9031  context->active_head = &context->extra[0];
9032  context->width = width;
9033  context->height = height;
9034  context->num_nodes = num_nodes;
9035  nk_rp_setup_allow_out_of_mem(context, 0);
9036 
9037  /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
9038  context->extra[0].x = 0;
9039  context->extra[0].y = 0;
9040  context->extra[0].next = &context->extra[1];
9041  context->extra[1].x = (nk_rp_coord) width;
9042  context->extra[1].y = 65535;
9043  context->extra[1].next = 0;
9044 }
9045 
9046 /* find minimum y position if it starts at x1 */
9047 NK_INTERN int
9048 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
9049  int x0, int width, int *pwaste)
9050 {
9051  struct nk_rp_node *node = first;
9052  int x1 = x0 + width;
9053  int min_y, visited_width, waste_area;
9054  NK_ASSERT(first->x <= x0);
9055  NK_UNUSED(c);
9056 
9057  NK_ASSERT(node->next->x > x0);
9058  /* we ended up handling this in the caller for efficiency */
9059  NK_ASSERT(node->x <= x0);
9060 
9061  min_y = 0;
9062  waste_area = 0;
9063  visited_width = 0;
9064  while (node->x < x1)
9065  {
9066  if (node->y > min_y) {
9067  /* raise min_y higher. */
9068  /* we've accounted for all waste up to min_y, */
9069  /* but we'll now add more waste for everything we've visited */
9070  waste_area += visited_width * (node->y - min_y);
9071  min_y = node->y;
9072  /* the first time through, visited_width might be reduced */
9073  if (node->x < x0)
9074  visited_width += node->next->x - x0;
9075  else
9076  visited_width += node->next->x - node->x;
9077  } else {
9078  /* add waste area */
9079  int under_width = node->next->x - node->x;
9080  if (under_width + visited_width > width)
9081  under_width = width - visited_width;
9082  waste_area += under_width * (min_y - node->y);
9083  visited_width += under_width;
9084  }
9085  node = node->next;
9086  }
9087  *pwaste = waste_area;
9088  return min_y;
9089 }
9090 
9091 NK_INTERN struct nk_rp__findresult
9092 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
9093 {
9094  int best_waste = (1<<30), best_x, best_y = (1 << 30);
9095  struct nk_rp__findresult fr;
9096  struct nk_rp_node **prev, *node, *tail, **best = 0;
9097 
9098  /* align to multiple of c->align */
9099  width = (width + c->align - 1);
9100  width -= width % c->align;
9101  NK_ASSERT(width % c->align == 0);
9102 
9103  node = c->active_head;
9104  prev = &c->active_head;
9105  while (node->x + width <= c->width) {
9106  int y,waste;
9107  y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
9108  /* actually just want to test BL */
9109  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
9110  /* bottom left */
9111  if (y < best_y) {
9112  best_y = y;
9113  best = prev;
9114  }
9115  } else {
9116  /* best-fit */
9117  if (y + height <= c->height) {
9118  /* can only use it if it first vertically */
9119  if (y < best_y || (y == best_y && waste < best_waste)) {
9120  best_y = y;
9121  best_waste = waste;
9122  best = prev;
9123  }
9124  }
9125  }
9126  prev = &node->next;
9127  node = node->next;
9128  }
9129  best_x = (best == 0) ? 0 : (*best)->x;
9130 
9131  /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
9132  /* */
9133  /* e.g, if fitting */
9134  /* */
9135  /* ____________________ */
9136  /* |____________________| */
9137  /* */
9138  /* into */
9139  /* */
9140  /* | | */
9141  /* | ____________| */
9142  /* |____________| */
9143  /* */
9144  /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
9145  /* */
9146  /* This makes BF take about 2x the time */
9147  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
9148  {
9149  tail = c->active_head;
9150  node = c->active_head;
9151  prev = &c->active_head;
9152  /* find first node that's admissible */
9153  while (tail->x < width)
9154  tail = tail->next;
9155  while (tail)
9156  {
9157  int xpos = tail->x - width;
9158  int y,waste;
9159  NK_ASSERT(xpos >= 0);
9160  /* find the left position that matches this */
9161  while (node->next->x <= xpos) {
9162  prev = &node->next;
9163  node = node->next;
9164  }
9165  NK_ASSERT(node->next->x > xpos && node->x <= xpos);
9166  y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
9167  if (y + height < c->height) {
9168  if (y <= best_y) {
9169  if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
9170  best_x = xpos;
9171  NK_ASSERT(y <= best_y);
9172  best_y = y;
9173  best_waste = waste;
9174  best = prev;
9175  }
9176  }
9177  }
9178  tail = tail->next;
9179  }
9180  }
9181  fr.prev_link = best;
9182  fr.x = best_x;
9183  fr.y = best_y;
9184  return fr;
9185 }
9186 
9187 NK_INTERN struct nk_rp__findresult
9188 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
9189 {
9190  /* find best position according to heuristic */
9191  struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
9192  struct nk_rp_node *node, *cur;
9193 
9194  /* bail if: */
9195  /* 1. it failed */
9196  /* 2. the best node doesn't fit (we don't always check this) */
9197  /* 3. we're out of memory */
9198  if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
9199  res.prev_link = 0;
9200  return res;
9201  }
9202 
9203  /* on success, create new node */
9204  node = context->free_head;
9205  node->x = (nk_rp_coord) res.x;
9206  node->y = (nk_rp_coord) (res.y + height);
9207 
9208  context->free_head = node->next;
9209 
9210  /* insert the new node into the right starting point, and */
9211  /* let 'cur' point to the remaining nodes needing to be */
9212  /* stitched back in */
9213  cur = *res.prev_link;
9214  if (cur->x < res.x) {
9215  /* preserve the existing one, so start testing with the next one */
9216  struct nk_rp_node *next = cur->next;
9217  cur->next = node;
9218  cur = next;
9219  } else {
9220  *res.prev_link = node;
9221  }
9222 
9223  /* from here, traverse cur and free the nodes, until we get to one */
9224  /* that shouldn't be freed */
9225  while (cur->next && cur->next->x <= res.x + width) {
9226  struct nk_rp_node *next = cur->next;
9227  /* move the current node to the free list */
9228  cur->next = context->free_head;
9229  context->free_head = cur;
9230  cur = next;
9231  }
9232  /* stitch the list back in */
9233  node->next = cur;
9234 
9235  if (cur->x < res.x + width)
9236  cur->x = (nk_rp_coord) (res.x + width);
9237  return res;
9238 }
9239 
9240 NK_INTERN int
9241 nk_rect_height_compare(const void *a, const void *b)
9242 {
9243  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9244  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9245  if (p->h > q->h)
9246  return -1;
9247  if (p->h < q->h)
9248  return 1;
9249  return (p->w > q->w) ? -1 : (p->w < q->w);
9250 }
9251 
9252 NK_INTERN int
9253 nk_rect_original_order(const void *a, const void *b)
9254 {
9255  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9256  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9257  return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
9258 }
9259 
9260 NK_INTERN void
9261 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
9262 {
9263  /* iterative quick sort */
9264  #define NK_MAX_SORT_STACK 64
9265  unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
9266  unsigned seed = len/2 * 69069+1;
9267  for (;;) {
9268  for (; left+1 < len; len++) {
9269  struct nk_rp_rect pivot, tmp;
9270  if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
9271  pivot = array[left+seed%(len-left)];
9272  seed = seed * 69069 + 1;
9273  stack[pos++] = len;
9274  for (right = left-1;;) {
9275  while (cmp(&array[++right], &pivot) < 0);
9276  while (cmp(&pivot, &array[--len]) < 0);
9277  if (right >= len) break;
9278  tmp = array[right];
9279  array[right] = array[len];
9280  array[len] = tmp;
9281  }
9282  }
9283  if (pos == 0) break;
9284  left = len;
9285  len = stack[--pos];
9286  }
9287  #undef NK_MAX_SORT_STACK
9288 }
9289 
9290 NK_INTERN void
9291 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
9292 {
9293  int i;
9294  /* we use the 'was_packed' field internally to allow sorting/unsorting */
9295  for (i=0; i < num_rects; ++i) {
9296  rects[i].was_packed = i;
9297  }
9298 
9299  /* sort according to heuristic */
9300  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
9301 
9302  for (i=0; i < num_rects; ++i) {
9303  struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
9304  if (fr.prev_link) {
9305  rects[i].x = (nk_rp_coord) fr.x;
9306  rects[i].y = (nk_rp_coord) fr.y;
9307  } else {
9308  rects[i].x = rects[i].y = NK_RP__MAXVAL;
9309  }
9310  }
9311 
9312  /* unsort */
9313  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
9314 
9315  /* set was_packed flags */
9316  for (i=0; i < num_rects; ++i)
9317  rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
9318 }
9319 
9320 /*
9321  * ==============================================================
9322  *
9323  * TRUETYPE
9324  *
9325  * ===============================================================
9326  */
9327 /* stb_truetype.h - v1.07 - public domain */
9328 #define NK_TT_MAX_OVERSAMPLE 8
9329 #define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1)
9330 
9331 struct nk_tt_bakedchar {
9332  unsigned short x0,y0,x1,y1;
9333  /* coordinates of bbox in bitmap */
9334  float xoff,yoff,xadvance;
9335 };
9336 
9337 struct nk_tt_aligned_quad{
9338  float x0,y0,s0,t0; /* top-left */
9339  float x1,y1,s1,t1; /* bottom-right */
9340 };
9341 
9342 struct nk_tt_packedchar {
9343  unsigned short x0,y0,x1,y1;
9344  /* coordinates of bbox in bitmap */
9345  float xoff,yoff,xadvance;
9346  float xoff2,yoff2;
9347 };
9348 
9349 struct nk_tt_pack_range {
9350  float font_size;
9351  int first_unicode_codepoint_in_range;
9352  /* if non-zero, then the chars are continuous, and this is the first codepoint */
9353  int *array_of_unicode_codepoints;
9354  /* if non-zero, then this is an array of unicode codepoints */
9355  int num_chars;
9356  struct nk_tt_packedchar *chardata_for_range; /* output */
9357  unsigned char h_oversample, v_oversample;
9358  /* don't set these, they're used internally */
9359 };
9360 
9361 struct nk_tt_pack_context {
9362  void *pack_info;
9363  int width;
9364  int height;
9365  int stride_in_bytes;
9366  int padding;
9367  unsigned int h_oversample, v_oversample;
9368  unsigned char *pixels;
9369  void *nodes;
9370 };
9371 
9372 struct nk_tt_fontinfo {
9373  const unsigned char* data; /* pointer to .ttf file */
9374  int fontstart;/* offset of start of font */
9375  int numGlyphs;/* number of glyphs, needed for range checking */
9376  int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
9377  int index_map; /* a cmap mapping for our chosen character encoding */
9378  int indexToLocFormat; /* format needed to map from glyph index to glyph */
9379 };
9380 
9381 enum {
9382  NK_TT_vmove=1,
9383  NK_TT_vline,
9384  NK_TT_vcurve
9385 };
9386 
9387 struct nk_tt_vertex {
9388  short x,y,cx,cy;
9389  unsigned char type,padding;
9390 };
9391 
9392 struct nk_tt__bitmap{
9393  int w,h,stride;
9394  unsigned char *pixels;
9395 };
9396 
9397 struct nk_tt__hheap_chunk {
9398  struct nk_tt__hheap_chunk *next;
9399 };
9400 struct nk_tt__hheap {
9401  struct nk_allocator alloc;
9402  struct nk_tt__hheap_chunk *head;
9403  void *first_free;
9404  int num_remaining_in_head_chunk;
9405 };
9406 
9407 struct nk_tt__edge {
9408  float x0,y0, x1,y1;
9409  int invert;
9410 };
9411 
9412 struct nk_tt__active_edge {
9413  struct nk_tt__active_edge *next;
9414  float fx,fdx,fdy;
9415  float direction;
9416  float sy;
9417  float ey;
9418 };
9419 struct nk_tt__point {float x,y;};
9420 
9421 #define NK_TT_MACSTYLE_DONTCARE 0
9422 #define NK_TT_MACSTYLE_BOLD 1
9423 #define NK_TT_MACSTYLE_ITALIC 2
9424 #define NK_TT_MACSTYLE_UNDERSCORE 4
9425 #define NK_TT_MACSTYLE_NONE 8
9426 /* <= not same as 0, this makes us check the bitfield is 0 */
9427 
9428 enum { /* platformID */
9429  NK_TT_PLATFORM_ID_UNICODE =0,
9430  NK_TT_PLATFORM_ID_MAC =1,
9431  NK_TT_PLATFORM_ID_ISO =2,
9432  NK_TT_PLATFORM_ID_MICROSOFT =3
9433 };
9434 
9435 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
9436  NK_TT_UNICODE_EID_UNICODE_1_0 =0,
9437  NK_TT_UNICODE_EID_UNICODE_1_1 =1,
9438  NK_TT_UNICODE_EID_ISO_10646 =2,
9439  NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
9440  NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
9441 };
9442 
9443 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
9444  NK_TT_MS_EID_SYMBOL =0,
9445  NK_TT_MS_EID_UNICODE_BMP =1,
9446  NK_TT_MS_EID_SHIFTJIS =2,
9447  NK_TT_MS_EID_UNICODE_FULL =10
9448 };
9449 
9450 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
9451  NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4,
9452  NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5,
9453  NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6,
9454  NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7
9455 };
9456 
9457 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
9458  /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
9459  NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410,
9460  NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411,
9461  NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412,
9462  NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419,
9463  NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409,
9464  NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D
9465 };
9466 
9467 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
9468  NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11,
9469  NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23,
9470  NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32,
9471  NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 ,
9472  NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 ,
9473  NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
9474  NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19
9475 };
9476 
9477 #define nk_ttBYTE(p) (* (const nk_byte *) (p))
9478 #define nk_ttCHAR(p) (* (const char *) (p))
9479 
9480 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
9481  #define nk_ttUSHORT(p) (* (nk_ushort *) (p))
9482  #define nk_ttSHORT(p) (* (nk_short *) (p))
9483  #define nk_ttULONG(p) (* (nk_uint *) (p))
9484  #define nk_ttLONG(p) (* (nk_int *) (p))
9485 #else
9486  static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
9487  static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); }
9488  static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
9489 #endif
9490 
9491 #define nk_tt_tag4(p,c0,c1,c2,c3)\
9492  ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
9493 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
9494 
9495 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9496  int glyph_index, struct nk_tt_vertex **pvertices);
9497 
9498 NK_INTERN nk_uint
9499 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
9500 {
9501  /* @OPTIMIZE: binary search */
9502  nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
9503  nk_uint tabledir = fontstart + 12;
9504  nk_int i;
9505  for (i = 0; i < num_tables; ++i) {
9506  nk_uint loc = tabledir + (nk_uint)(16*i);
9507  if (nk_tt_tag(data+loc+0, tag))
9508  return nk_ttULONG(data+loc+8);
9509  }
9510  return 0;
9511 }
9512 
9513 NK_INTERN int
9514 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
9515 {
9516  nk_uint cmap, t;
9517  nk_int i,numTables;
9518  const nk_byte *data = (const nk_byte *) data2;
9519 
9520  info->data = data;
9521  info->fontstart = fontstart;
9522 
9523  cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */
9524  info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
9525  info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
9526  info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
9527  info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
9528  info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
9529  info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
9530  if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
9531  return 0;
9532 
9533  t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
9534  if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
9535  else info->numGlyphs = 0xffff;
9536 
9537  /* find a cmap encoding table we understand *now* to avoid searching */
9538  /* later. (todo: could make this installable) */
9539  /* the same regardless of glyph. */
9540  numTables = nk_ttUSHORT(data + cmap + 2);
9541  info->index_map = 0;
9542  for (i=0; i < numTables; ++i)
9543  {
9544  nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
9545  /* find an encoding we understand: */
9546  switch(nk_ttUSHORT(data+encoding_record)) {
9547  case NK_TT_PLATFORM_ID_MICROSOFT:
9548  switch (nk_ttUSHORT(data+encoding_record+2)) {
9549  case NK_TT_MS_EID_UNICODE_BMP:
9550  case NK_TT_MS_EID_UNICODE_FULL:
9551  /* MS/Unicode */
9552  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9553  break;
9554  default: break;
9555  } break;
9556  case NK_TT_PLATFORM_ID_UNICODE:
9557  /* Mac/iOS has these */
9558  /* all the encodingIDs are unicode, so we don't bother to check it */
9559  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9560  break;
9561  default: break;
9562  }
9563  }
9564  if (info->index_map == 0)
9565  return 0;
9566  info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
9567  return 1;
9568 }
9569 
9570 NK_INTERN int
9571 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
9572 {
9573  const nk_byte *data = info->data;
9574  nk_uint index_map = (nk_uint)info->index_map;
9575 
9576  nk_ushort format = nk_ttUSHORT(data + index_map + 0);
9577  if (format == 0) { /* apple byte encoding */
9578  nk_int bytes = nk_ttUSHORT(data + index_map + 2);
9579  if (unicode_codepoint < bytes-6)
9580  return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
9581  return 0;
9582  } else if (format == 6) {
9583  nk_uint first = nk_ttUSHORT(data + index_map + 6);
9584  nk_uint count = nk_ttUSHORT(data + index_map + 8);
9585  if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
9586  return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
9587  return 0;
9588  } else if (format == 2) {
9589  NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
9590  return 0;
9591  } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
9592  nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
9593  nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
9594  nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
9595  nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
9596 
9597  /* do a binary search of the segments */
9598  nk_uint endCount = index_map + 14;
9599  nk_uint search = endCount;
9600 
9601  if (unicode_codepoint > 0xffff)
9602  return 0;
9603 
9604  /* they lie from endCount .. endCount + segCount */
9605  /* but searchRange is the nearest power of two, so... */
9606  if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
9607  search += (nk_uint)(rangeShift*2);
9608 
9609  /* now decrement to bias correctly to find smallest */
9610  search -= 2;
9611  while (entrySelector) {
9612  nk_ushort end;
9613  searchRange >>= 1;
9614  end = nk_ttUSHORT(data + search + searchRange*2);
9615  if (unicode_codepoint > end)
9616  search += (nk_uint)(searchRange*2);
9617  --entrySelector;
9618  }
9619  search += 2;
9620 
9621  {
9622  nk_ushort offset, start;
9623  nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
9624 
9625  NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
9626  start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
9627  if (unicode_codepoint < start)
9628  return 0;
9629 
9630  offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
9631  if (offset == 0)
9632  return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
9633 
9634  return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
9635  }
9636  } else if (format == 12 || format == 13) {
9637  nk_uint ngroups = nk_ttULONG(data+index_map+12);
9638  nk_int low,high;
9639  low = 0; high = (nk_int)ngroups;
9640  /* Binary search the right group. */
9641  while (low < high) {
9642  nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
9643  nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
9644  nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
9645  if ((nk_uint) unicode_codepoint < start_char)
9646  high = mid;
9647  else if ((nk_uint) unicode_codepoint > end_char)
9648  low = mid+1;
9649  else {
9650  nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
9651  if (format == 12)
9652  return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
9653  else /* format == 13 */
9654  return (int)start_glyph;
9655  }
9656  }
9657  return 0; /* not found */
9658  }
9659  /* @TODO */
9660  NK_ASSERT(0);
9661  return 0;
9662 }
9663 
9664 NK_INTERN void
9665 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
9666 {
9667  v->type = type;
9668  v->x = (nk_short) x;
9669  v->y = (nk_short) y;
9670  v->cx = (nk_short) cx;
9671  v->cy = (nk_short) cy;
9672 }
9673 
9674 NK_INTERN int
9675 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
9676 {
9677  int g1,g2;
9678  if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
9679  if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */
9680 
9681  if (info->indexToLocFormat == 0) {
9682  g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
9683  g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
9684  } else {
9685  g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
9686  g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
9687  }
9688  return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
9689 }
9690 
9691 NK_INTERN int
9692 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
9693  int *x0, int *y0, int *x1, int *y1)
9694 {
9695  int g = nk_tt__GetGlyfOffset(info, glyph_index);
9696  if (g < 0) return 0;
9697 
9698  if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
9699  if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
9700  if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
9701  if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
9702  return 1;
9703 }
9704 
9705 NK_INTERN int
9706 stbtt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
9707  int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
9708 {
9709  if (start_off) {
9710  if (was_off)
9711  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
9712  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
9713  } else {
9714  if (was_off)
9715  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
9716  else
9717  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
9718  }
9719  return num_vertices;
9720 }
9721 
9722 NK_INTERN int
9723 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9724  int glyph_index, struct nk_tt_vertex **pvertices)
9725 {
9726  nk_short numberOfContours;
9727  const nk_byte *endPtsOfContours;
9728  const nk_byte *data = info->data;
9729  struct nk_tt_vertex *vertices=0;
9730  int num_vertices=0;
9731  int g = nk_tt__GetGlyfOffset(info, glyph_index);
9732  *pvertices = 0;
9733 
9734  if (g < 0) return 0;
9735  numberOfContours = nk_ttSHORT(data + g);
9736  if (numberOfContours > 0) {
9737  nk_byte flags=0,flagcount;
9738  nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
9739  nk_int x,y,cx,cy,sx,sy, scx,scy;
9740  const nk_byte *points;
9741  endPtsOfContours = (data + g + 10);
9742  ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
9743  points = data + g + 10 + numberOfContours * 2 + 2 + ins;
9744 
9745  n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
9746  m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */
9747  vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
9748  if (vertices == 0)
9749  return 0;
9750 
9751  next_move = 0;
9752  flagcount=0;
9753 
9754  /* in first pass, we load uninterpreted data into the allocated array */
9755  /* above, shifted to the end of the array so we won't overwrite it when */
9756  /* we create our final data starting from the front */
9757  off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
9758 
9759  /* first load flags */
9760  for (i=0; i < n; ++i) {
9761  if (flagcount == 0) {
9762  flags = *points++;
9763  if (flags & 8)
9764  flagcount = *points++;
9765  } else --flagcount;
9766  vertices[off+i].type = flags;
9767  }
9768 
9769  /* now load x coordinates */
9770  x=0;
9771  for (i=0; i < n; ++i) {
9772  flags = vertices[off+i].type;
9773  if (flags & 2) {
9774  nk_short dx = *points++;
9775  x += (flags & 16) ? dx : -dx; /* ??? */
9776  } else {
9777  if (!(flags & 16)) {
9778  x = x + (nk_short) (points[0]*256 + points[1]);
9779  points += 2;
9780  }
9781  }
9782  vertices[off+i].x = (nk_short) x;
9783  }
9784 
9785  /* now load y coordinates */
9786  y=0;
9787  for (i=0; i < n; ++i) {
9788  flags = vertices[off+i].type;
9789  if (flags & 4) {
9790  nk_short dy = *points++;
9791  y += (flags & 32) ? dy : -dy; /* ??? */
9792  } else {
9793  if (!(flags & 32)) {
9794  y = y + (nk_short) (points[0]*256 + points[1]);
9795  points += 2;
9796  }
9797  }
9798  vertices[off+i].y = (nk_short) y;
9799  }
9800 
9801  /* now convert them to our format */
9802  num_vertices=0;
9803  sx = sy = cx = cy = scx = scy = 0;
9804  for (i=0; i < n; ++i)
9805  {
9806  flags = vertices[off+i].type;
9807  x = (nk_short) vertices[off+i].x;
9808  y = (nk_short) vertices[off+i].y;
9809 
9810  if (next_move == i) {
9811  if (i != 0)
9812  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
9813 
9814  /* now start the new one */
9815  start_off = !(flags & 1);
9816  if (start_off) {
9817  /* if we start off with an off-curve point, then when we need to find a point on the curve */
9818  /* where we can start, and we need to save some state for when we wraparound. */
9819  scx = x;
9820  scy = y;
9821  if (!(vertices[off+i+1].type & 1)) {
9822  /* next point is also a curve point, so interpolate an on-point curve */
9823  sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
9824  sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
9825  } else {
9826  /* otherwise just use the next point as our start point */
9827  sx = (nk_int) vertices[off+i+1].x;
9828  sy = (nk_int) vertices[off+i+1].y;
9829  ++i; /* we're using point i+1 as the starting point, so skip it */
9830  }
9831  } else {
9832  sx = x;
9833  sy = y;
9834  }
9835  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
9836  was_off = 0;
9837  next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
9838  ++j;
9839  } else {
9840  if (!(flags & 1))
9841  { /* if it's a curve */
9842  if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
9843  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
9844  cx = x;
9845  cy = y;
9846  was_off = 1;
9847  } else {
9848  if (was_off)
9849  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
9850  else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
9851  was_off = 0;
9852  }
9853  }
9854  }
9855  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
9856  } else if (numberOfContours == -1) {
9857  /* Compound shapes. */
9858  int more = 1;
9859  const nk_byte *comp = data + g + 10;
9860  num_vertices = 0;
9861  vertices = 0;
9862 
9863  while (more)
9864  {
9865  nk_ushort flags, gidx;
9866  int comp_num_verts = 0, i;
9867  struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
9868  float mtx[6] = {1,0,0,1,0,0}, m, n;
9869 
9870  flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
9871  gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
9872 
9873  if (flags & 2) { /* XY values */
9874  if (flags & 1) { /* shorts */
9875  mtx[4] = nk_ttSHORT(comp); comp+=2;
9876  mtx[5] = nk_ttSHORT(comp); comp+=2;
9877  } else {
9878  mtx[4] = nk_ttCHAR(comp); comp+=1;
9879  mtx[5] = nk_ttCHAR(comp); comp+=1;
9880  }
9881  } else {
9882  /* @TODO handle matching point */
9883  NK_ASSERT(0);
9884  }
9885  if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
9886  mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9887  mtx[1] = mtx[2] = 0;
9888  } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
9889  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9890  mtx[1] = mtx[2] = 0;
9891  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9892  } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
9893  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9894  mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9895  mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9896  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
9897  }
9898 
9899  /* Find transformation scales. */
9900  m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
9901  n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
9902 
9903  /* Get indexed glyph. */
9904  comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
9905  if (comp_num_verts > 0)
9906  {
9907  /* Transform vertices. */
9908  for (i = 0; i < comp_num_verts; ++i) {
9909  struct nk_tt_vertex* v = &comp_verts[i];
9910  short x,y;
9911  x=v->x; y=v->y;
9912  v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
9913  v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
9914  x=v->cx; y=v->cy;
9915  v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
9916  v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
9917  }
9918  /* Append vertices. */
9919  tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
9920  (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
9921  if (!tmp) {
9922  if (vertices) alloc->free(alloc->userdata, vertices);
9923  if (comp_verts) alloc->free(alloc->userdata, comp_verts);
9924  return 0;
9925  }
9926  if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
9927  NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
9928  if (vertices) alloc->free(alloc->userdata,vertices);
9929  vertices = tmp;
9930  alloc->free(alloc->userdata,comp_verts);
9931  num_vertices += comp_num_verts;
9932  }
9933  /* More components ? */
9934  more = flags & (1<<5);
9935  }
9936  } else if (numberOfContours < 0) {
9937  /* @TODO other compound variations? */
9938  NK_ASSERT(0);
9939  } else {
9940  /* numberOfCounters == 0, do nothing */
9941  }
9942  *pvertices = vertices;
9943  return num_vertices;
9944 }
9945 
9946 NK_INTERN void
9947 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
9948  int *advanceWidth, int *leftSideBearing)
9949 {
9950  nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
9951  if (glyph_index < numOfLongHorMetrics) {
9952  if (advanceWidth)
9953  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
9954  if (leftSideBearing)
9955  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
9956  } else {
9957  if (advanceWidth)
9958  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
9959  if (leftSideBearing)
9960  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
9961  }
9962 }
9963 
9964 NK_INTERN void
9965 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
9966  int *ascent, int *descent, int *lineGap)
9967 {
9968  if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4);
9969  if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
9970  if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
9971 }
9972 
9973 NK_INTERN float
9974 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
9975 {
9976  int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
9977  return (float) height / (float)fheight;
9978 }
9979 
9980 NK_INTERN float
9981 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
9982 {
9983  int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
9984  return pixels / (float)unitsPerEm;
9985 }
9986 
9987 /*-------------------------------------------------------------
9988  * antialiasing software rasterizer
9989  * --------------------------------------------------------------*/
9990 NK_INTERN void
9991 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
9992  int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
9993  int *ix0, int *iy0, int *ix1, int *iy1)
9994 {
9995  int x0,y0,x1,y1;
9996  if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
9997  /* e.g. space character */
9998  if (ix0) *ix0 = 0;
9999  if (iy0) *iy0 = 0;
10000  if (ix1) *ix1 = 0;
10001  if (iy1) *iy1 = 0;
10002  } else {
10003  /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
10004  if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
10005  if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
10006  if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
10007  if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
10008  }
10009 }
10010 
10011 NK_INTERN void
10012 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
10013  float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
10014 {
10015  nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
10016 }
10017 
10018 /*-------------------------------------------------------------
10019  * Rasterizer
10020  * --------------------------------------------------------------*/
10021 NK_INTERN void*
10022 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
10023 {
10024  if (hh->first_free) {
10025  void *p = hh->first_free;
10026  hh->first_free = * (void **) p;
10027  return p;
10028  } else {
10029  if (hh->num_remaining_in_head_chunk == 0) {
10030  int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
10031  struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
10032  hh->alloc.alloc(hh->alloc.userdata, 0,
10033  sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
10034  if (c == 0) return 0;
10035  c->next = hh->head;
10036  hh->head = c;
10037  hh->num_remaining_in_head_chunk = count;
10038  }
10039  --hh->num_remaining_in_head_chunk;
10040  return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
10041  }
10042 }
10043 
10044 NK_INTERN void
10045 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
10046 {
10047  *(void **) p = hh->first_free;
10048  hh->first_free = p;
10049 }
10050 
10051 NK_INTERN void
10052 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
10053 {
10054  struct nk_tt__hheap_chunk *c = hh->head;
10055  while (c) {
10056  struct nk_tt__hheap_chunk *n = c->next;
10057  hh->alloc.free(hh->alloc.userdata, c);
10058  c = n;
10059  }
10060 }
10061 
10062 NK_INTERN struct nk_tt__active_edge*
10063 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
10064  int off_x, float start_point)
10065 {
10066  struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
10067  nk_tt__hheap_alloc(hh, sizeof(*z));
10068  float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
10069  /*STBTT_assert(e->y0 <= start_point); */
10070  if (!z) return z;
10071  z->fdx = dxdy;
10072  z->fdy = (dxdy != 0) ? (1/dxdy): 0;
10073  z->fx = e->x0 + dxdy * (start_point - e->y0);
10074  z->fx -= (float)off_x;
10075  z->direction = e->invert ? 1.0f : -1.0f;
10076  z->sy = e->y0;
10077  z->ey = e->y1;
10078  z->next = 0;
10079  return z;
10080 }
10081 
10082 NK_INTERN void
10083 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
10084  float x0, float y0, float x1, float y1)
10085 {
10086  if (y0 == y1) return;
10087  NK_ASSERT(y0 < y1);
10088  NK_ASSERT(e->sy <= e->ey);
10089  if (y0 > e->ey) return;
10090  if (y1 < e->sy) return;
10091  if (y0 < e->sy) {
10092  x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
10093  y0 = e->sy;
10094  }
10095  if (y1 > e->ey) {
10096  x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
10097  y1 = e->ey;
10098  }
10099 
10100  if (x0 == x) NK_ASSERT(x1 <= x+1);
10101  else if (x0 == x+1) NK_ASSERT(x1 >= x);
10102  else if (x0 <= x) NK_ASSERT(x1 <= x);
10103  else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
10104  else NK_ASSERT(x1 >= x && x1 <= x+1);
10105 
10106  if (x0 <= x && x1 <= x)
10107  scanline[x] += e->direction * (y1-y0);
10108  else if (x0 >= x+1 && x1 >= x+1);
10109  else {
10110  NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
10111  /* coverage = 1 - average x position */
10112  scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
10113  }
10114 }
10115 
10116 NK_INTERN void
10117 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
10118  struct nk_tt__active_edge *e, float y_top)
10119 {
10120  float y_bottom = y_top+1;
10121  while (e)
10122  {
10123  /* brute force every pixel */
10124  /* compute intersection points with top & bottom */
10125  NK_ASSERT(e->ey >= y_top);
10126  if (e->fdx == 0) {
10127  float x0 = e->fx;
10128  if (x0 < len) {
10129  if (x0 >= 0) {
10130  nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
10131  nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
10132  } else {
10133  nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
10134  }
10135  }
10136  } else {
10137  float x0 = e->fx;
10138  float dx = e->fdx;
10139  float xb = x0 + dx;
10140  float x_top, x_bottom;
10141  float y0,y1;
10142  float dy = e->fdy;
10143  NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
10144 
10145  /* compute endpoints of line segment clipped to this scanline (if the */
10146  /* line segment starts on this scanline. x0 is the intersection of the */
10147  /* line with y_top, but that may be off the line segment. */
10148  if (e->sy > y_top) {
10149  x_top = x0 + dx * (e->sy - y_top);
10150  y0 = e->sy;
10151  } else {
10152  x_top = x0;
10153  y0 = y_top;
10154  }
10155 
10156  if (e->ey < y_bottom) {
10157  x_bottom = x0 + dx * (e->ey - y_top);
10158  y1 = e->ey;
10159  } else {
10160  x_bottom = xb;
10161  y1 = y_bottom;
10162  }
10163 
10164  if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
10165  {
10166  /* from here on, we don't have to range check x values */
10167  if ((int) x_top == (int) x_bottom) {
10168  float height;
10169  /* simple case, only spans one pixel */
10170  int x = (int) x_top;
10171  height = y1 - y0;
10172  NK_ASSERT(x >= 0 && x < len);
10173  scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height;
10174  scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
10175  } else {
10176  int x,x1,x2;
10177  float y_crossing, step, sign, area;
10178  /* covers 2+ pixels */
10179  if (x_top > x_bottom)
10180  {
10181  /* flip scanline vertically; signed area is the same */
10182  float t;
10183  y0 = y_bottom - (y0 - y_top);
10184  y1 = y_bottom - (y1 - y_top);
10185  t = y0; y0 = y1; y1 = t;
10186  t = x_bottom; x_bottom = x_top; x_top = t;
10187  dx = -dx;
10188  dy = -dy;
10189  t = x0; x0 = xb; xb = t;
10190  }
10191 
10192  x1 = (int) x_top;
10193  x2 = (int) x_bottom;
10194  /* compute intersection with y axis at x1+1 */
10195  y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
10196 
10197  sign = e->direction;
10198  /* area of the rectangle covered from y0..y_crossing */
10199  area = sign * (y_crossing-y0);
10200  /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
10201  scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
10202 
10203  step = sign * dy;
10204  for (x = x1+1; x < x2; ++x) {
10205  scanline[x] += area + step/2;
10206  area += step;
10207  }
10208  y_crossing += (float)dy * (float)(x2 - (x1+1));
10209 
10210  scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
10211  scanline_fill[x2] += sign * (y1-y0);
10212  }
10213  }
10214  else
10215  {
10216  /* if edge goes outside of box we're drawing, we require */
10217  /* clipping logic. since this does not match the intended use */
10218  /* of this library, we use a different, very slow brute */
10219  /* force implementation */
10220  int x;
10221  for (x=0; x < len; ++x)
10222  {
10223  /* cases: */
10224  /* */
10225  /* there can be up to two intersections with the pixel. any intersection */
10226  /* with left or right edges can be handled by splitting into two (or three) */
10227  /* regions. intersections with top & bottom do not necessitate case-wise logic. */
10228  /* */
10229  /* the old way of doing this found the intersections with the left & right edges, */
10230  /* then used some simple logic to produce up to three segments in sorted order */
10231  /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
10232  /* across the x border, then the corresponding y position might not be distinct */
10233  /* from the other y segment, and it might ignored as an empty segment. to avoid */
10234  /* that, we need to explicitly produce segments based on x positions. */
10235 
10236  /* rename variables to clear pairs */
10237  float ya = y_top;
10238  float x1 = (float) (x);
10239  float x2 = (float) (x+1);
10240  float x3 = xb;
10241  float y3 = y_bottom;
10242  float yb,y2;
10243 
10244  yb = ((float)x - x0) / dx + y_top;
10245  y2 = ((float)x+1 - x0) / dx + y_top;
10246 
10247  if (x0 < x1 && x3 > x2) { /* three segments descending down-right */
10248  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10249  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
10250  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10251  } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */
10252  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10253  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
10254  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10255  } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */
10256  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10257  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10258  } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */
10259  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10260  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10261  } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */
10262  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10263  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10264  } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */
10265  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10266  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10267  } else { /* one segment */
10268  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
10269  }
10270  }
10271  }
10272  }
10273  e = e->next;
10274  }
10275 }
10276 
10277 /* directly AA rasterize edges w/o supersampling */
10278 NK_INTERN void
10279 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
10280  int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
10281 {
10282  struct nk_tt__hheap hh;
10283  struct nk_tt__active_edge *active = 0;
10284  int y,j=0, i;
10285  float scanline_data[129], *scanline, *scanline2;
10286 
10287  NK_UNUSED(vsubsample);
10288  nk_zero_struct(hh);
10289  hh.alloc = *alloc;
10290 
10291  if (result->w > 64)
10292  scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
10293  else scanline = scanline_data;
10294 
10295  scanline2 = scanline + result->w;
10296  y = off_y;
10297  e[n].y0 = (float) (off_y + result->h) + 1;
10298 
10299  while (j < result->h)
10300  {
10301  /* find center of pixel for this scanline */
10302  float scan_y_top = (float)y + 0.0f;
10303  float scan_y_bottom = (float)y + 1.0f;
10304  struct nk_tt__active_edge **step = &active;
10305 
10306  NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
10307  NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
10308 
10309  /* update all active edges; */
10310  /* remove all active edges that terminate before the top of this scanline */
10311  while (*step) {
10312  struct nk_tt__active_edge * z = *step;
10313  if (z->ey <= scan_y_top) {
10314  *step = z->next; /* delete from list */
10315  NK_ASSERT(z->direction);
10316  z->direction = 0;
10317  nk_tt__hheap_free(&hh, z);
10318  } else {
10319  step = &((*step)->next); /* advance through list */
10320  }
10321  }
10322 
10323  /* insert all edges that start before the bottom of this scanline */
10324  while (e->y0 <= scan_y_bottom) {
10325  if (e->y0 != e->y1) {
10326  struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
10327  if (z != 0) {
10328  NK_ASSERT(z->ey >= scan_y_top);
10329  /* insert at front */
10330  z->next = active;
10331  active = z;
10332  }
10333  }
10334  ++e;
10335  }
10336 
10337  /* now process all active edges */
10338  if (active)
10339  nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
10340 
10341  {
10342  float sum = 0;
10343  for (i=0; i < result->w; ++i) {
10344  float k;
10345  int m;
10346  sum += scanline2[i];
10347  k = scanline[i] + sum;
10348  k = (float) NK_ABS(k) * 255.0f + 0.5f;
10349  m = (int) k;
10350  if (m > 255) m = 255;
10351  result->pixels[j*result->stride + i] = (unsigned char) m;
10352  }
10353  }
10354  /* advance all the edges */
10355  step = &active;
10356  while (*step) {
10357  struct nk_tt__active_edge *z = *step;
10358  z->fx += z->fdx; /* advance to position for current scanline */
10359  step = &((*step)->next); /* advance through list */
10360  }
10361  ++y;
10362  ++j;
10363  }
10364  nk_tt__hheap_cleanup(&hh);
10365  if (scanline != scanline_data)
10366  alloc->free(alloc->userdata, scanline);
10367 }
10368 
10369 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0)
10370 NK_INTERN void
10371 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
10372 {
10373  int i,j;
10374  for (i=1; i < n; ++i) {
10375  struct nk_tt__edge t = p[i], *a = &t;
10376  j = i;
10377  while (j > 0) {
10378  struct nk_tt__edge *b = &p[j-1];
10379  int c = NK_TT__COMPARE(a,b);
10380  if (!c) break;
10381  p[j] = p[j-1];
10382  --j;
10383  }
10384  if (i != j)
10385  p[j] = t;
10386  }
10387 }
10388 
10389 NK_INTERN void
10390 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
10391 {
10392  /* threshold for transitioning to insertion sort */
10393  while (n > 12) {
10394  struct nk_tt__edge t;
10395  int c01,c12,c,m,i,j;
10396 
10397  /* compute median of three */
10398  m = n >> 1;
10399  c01 = NK_TT__COMPARE(&p[0],&p[m]);
10400  c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
10401 
10402  /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
10403  if (c01 != c12) {
10404  /* otherwise, we'll need to swap something else to middle */
10405  int z;
10406  c = NK_TT__COMPARE(&p[0],&p[n-1]);
10407  /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
10408  /* 0<mid && mid>n: 0>n => 0; 0<n => n */
10409  z = (c == c12) ? 0 : n-1;
10410  t = p[z];
10411  p[z] = p[m];
10412  p[m] = t;
10413  }
10414 
10415  /* now p[m] is the median-of-three */
10416  /* swap it to the beginning so it won't move around */
10417  t = p[0];
10418  p[0] = p[m];
10419  p[m] = t;
10420 
10421  /* partition loop */
10422  i=1;
10423  j=n-1;
10424  for(;;) {
10425  /* handling of equality is crucial here */
10426  /* for sentinels & efficiency with duplicates */
10427  for (;;++i) {
10428  if (!NK_TT__COMPARE(&p[i], &p[0])) break;
10429  }
10430  for (;;--j) {
10431  if (!NK_TT__COMPARE(&p[0], &p[j])) break;
10432  }
10433 
10434  /* make sure we haven't crossed */
10435  if (i >= j) break;
10436  t = p[i];
10437  p[i] = p[j];
10438  p[j] = t;
10439 
10440  ++i;
10441  --j;
10442 
10443  }
10444 
10445  /* recurse on smaller side, iterate on larger */
10446  if (j < (n-i)) {
10447  nk_tt__sort_edges_quicksort(p,j);
10448  p = p+i;
10449  n = n-i;
10450  } else {
10451  nk_tt__sort_edges_quicksort(p+i, n-i);
10452  n = j;
10453  }
10454  }
10455 }
10456 
10457 NK_INTERN void
10458 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
10459 {
10460  nk_tt__sort_edges_quicksort(p, n);
10461  nk_tt__sort_edges_ins_sort(p, n);
10462 }
10463 
10464 NK_INTERN void
10465 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
10466  int *wcount, int windings, float scale_x, float scale_y,
10467  float shift_x, float shift_y, int off_x, int off_y, int invert,
10468  struct nk_allocator *alloc)
10469 {
10470  float y_scale_inv = invert ? -scale_y : scale_y;
10471  struct nk_tt__edge *e;
10472  int n,i,j,k,m;
10473  int vsubsample = 1;
10474  /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
10475 
10476  /* now we have to blow out the windings into explicit edge lists */
10477  n = 0;
10478  for (i=0; i < windings; ++i)
10479  n += wcount[i];
10480 
10481  e = (struct nk_tt__edge*)
10482  alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
10483  if (e == 0) return;
10484  n = 0;
10485 
10486  m=0;
10487  for (i=0; i < windings; ++i)
10488  {
10489  struct nk_tt__point *p = pts + m;
10490  m += wcount[i];
10491  j = wcount[i]-1;
10492  for (k=0; k < wcount[i]; j=k++) {
10493  int a=k,b=j;
10494  /* skip the edge if horizontal */
10495  if (p[j].y == p[k].y)
10496  continue;
10497 
10498  /* add edge from j to k to the list */
10499  e[n].invert = 0;
10500  if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
10501  e[n].invert = 1;
10502  a=j,b=k;
10503  }
10504  e[n].x0 = p[a].x * scale_x + shift_x;
10505  e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
10506  e[n].x1 = p[b].x * scale_x + shift_x;
10507  e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
10508  ++n;
10509  }
10510  }
10511 
10512  /* now sort the edges by their highest point (should snap to integer, and then by x) */
10513  /*STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */
10514  nk_tt__sort_edges(e, n);
10515  /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
10516  nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
10517  alloc->free(alloc->userdata, e);
10518 }
10519 
10520 NK_INTERN void
10521 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
10522 {
10523  if (!points) return; /* during first pass, it's unallocated */
10524  points[n].x = x;
10525  points[n].y = y;
10526 }
10527 
10528 NK_INTERN int
10529 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
10530  float x0, float y0, float x1, float y1, float x2, float y2,
10531  float objspace_flatness_squared, int n)
10532 {
10533  /* tesselate until threshold p is happy...
10534  * @TODO warped to compensate for non-linear stretching */
10535  /* midpoint */
10536  float mx = (x0 + 2*x1 + x2)/4;
10537  float my = (y0 + 2*y1 + y2)/4;
10538  /* versus directly drawn line */
10539  float dx = (x0+x2)/2 - mx;
10540  float dy = (y0+y2)/2 - my;
10541  if (n > 16) /* 65536 segments on one curve better be enough! */
10542  return 1;
10543 
10544  /* half-pixel error allowed... need to be smaller if AA */
10545  if (dx*dx+dy*dy > objspace_flatness_squared) {
10546  nk_tt__tesselate_curve(points, num_points, x0,y0,
10547  (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
10548  nk_tt__tesselate_curve(points, num_points, mx,my,
10549  (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
10550  } else {
10551  nk_tt__add_point(points, *num_points,x2,y2);
10552  *num_points = *num_points+1;
10553  }
10554  return 1;
10555 }
10556 
10557 /* returns number of contours */
10558 NK_INTERN struct nk_tt__point*
10559 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
10560  float objspace_flatness, int **contour_lengths, int *num_contours,
10561  struct nk_allocator *alloc)
10562 {
10563  struct nk_tt__point *points=0;
10564  int num_points=0;
10565  float objspace_flatness_squared = objspace_flatness * objspace_flatness;
10566  int i;
10567  int n=0;
10568  int start=0;
10569  int pass;
10570 
10571  /* count how many "moves" there are to get the contour count */
10572  for (i=0; i < num_verts; ++i)
10573  if (vertices[i].type == NK_TT_vmove) ++n;
10574 
10575  *num_contours = n;
10576  if (n == 0) return 0;
10577 
10578  *contour_lengths = (int *)
10579  alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
10580  if (*contour_lengths == 0) {
10581  *num_contours = 0;
10582  return 0;
10583  }
10584 
10585  /* make two passes through the points so we don't need to realloc */
10586  for (pass=0; pass < 2; ++pass)
10587  {
10588  float x=0,y=0;
10589  if (pass == 1) {
10590  points = (struct nk_tt__point *)
10591  alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
10592  if (points == 0) goto error;
10593  }
10594  num_points = 0;
10595  n= -1;
10596 
10597  for (i=0; i < num_verts; ++i)
10598  {
10599  switch (vertices[i].type) {
10600  case NK_TT_vmove:
10601  /* start the next contour */
10602  if (n >= 0)
10603  (*contour_lengths)[n] = num_points - start;
10604  ++n;
10605  start = num_points;
10606 
10607  x = vertices[i].x, y = vertices[i].y;
10608  nk_tt__add_point(points, num_points++, x,y);
10609  break;
10610  case NK_TT_vline:
10611  x = vertices[i].x, y = vertices[i].y;
10612  nk_tt__add_point(points, num_points++, x, y);
10613  break;
10614  case NK_TT_vcurve:
10615  nk_tt__tesselate_curve(points, &num_points, x,y,
10616  vertices[i].cx, vertices[i].cy,
10617  vertices[i].x, vertices[i].y,
10618  objspace_flatness_squared, 0);
10619  x = vertices[i].x, y = vertices[i].y;
10620  break;
10621  default: break;
10622  }
10623  }
10624  (*contour_lengths)[n] = num_points - start;
10625  }
10626  return points;
10627 
10628 error:
10629  alloc->free(alloc->userdata, points);
10630  alloc->free(alloc->userdata, *contour_lengths);
10631  *contour_lengths = 0;
10632  *num_contours = 0;
10633  return 0;
10634 }
10635 
10636 NK_INTERN void
10637 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
10638  struct nk_tt_vertex *vertices, int num_verts,
10639  float scale_x, float scale_y, float shift_x, float shift_y,
10640  int x_off, int y_off, int invert, struct nk_allocator *alloc)
10641 {
10642  float scale = scale_x > scale_y ? scale_y : scale_x;
10643  int winding_count, *winding_lengths;
10644  struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
10645  flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
10646 
10647  NK_ASSERT(alloc);
10648  if (windings) {
10649  nk_tt__rasterize(result, windings, winding_lengths, winding_count,
10650  scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
10651  alloc->free(alloc->userdata, winding_lengths);
10652  alloc->free(alloc->userdata, windings);
10653  }
10654 }
10655 
10656 NK_INTERN void
10657 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
10658  int out_w, int out_h, int out_stride, float scale_x, float scale_y,
10659  float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
10660 {
10661  int ix0,iy0;
10662  struct nk_tt_vertex *vertices;
10663  int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
10664  struct nk_tt__bitmap gbm;
10665 
10666  nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
10667  shift_y, &ix0,&iy0,0,0);
10668  gbm.pixels = output;
10669  gbm.w = out_w;
10670  gbm.h = out_h;
10671  gbm.stride = out_stride;
10672 
10673  if (gbm.w && gbm.h)
10674  nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
10675  shift_x, shift_y, ix0,iy0, 1, alloc);
10676  alloc->free(alloc->userdata, vertices);
10677 }
10678 
10679 /*-------------------------------------------------------------
10680  * Bitmap baking
10681  * --------------------------------------------------------------*/
10682 NK_INTERN int
10683 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
10684  int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
10685 {
10686  int num_nodes = pw - padding;
10687  struct nk_rp_context *context = (struct nk_rp_context *)
10688  alloc->alloc(alloc->userdata,0, sizeof(*context));
10689  struct nk_rp_node *nodes = (struct nk_rp_node*)
10690  alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes));
10691 
10692  if (context == 0 || nodes == 0) {
10693  if (context != 0) alloc->free(alloc->userdata, context);
10694  if (nodes != 0) alloc->free(alloc->userdata, nodes);
10695  return 0;
10696  }
10697 
10698  spc->width = pw;
10699  spc->height = ph;
10700  spc->pixels = pixels;
10701  spc->pack_info = context;
10702  spc->nodes = nodes;
10703  spc->padding = padding;
10704  spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
10705  spc->h_oversample = 1;
10706  spc->v_oversample = 1;
10707 
10708  nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
10709  if (pixels)
10710  NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
10711  return 1;
10712 }
10713 
10714 NK_INTERN void
10715 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
10716 {
10717  alloc->free(alloc->userdata, spc->nodes);
10718  alloc->free(alloc->userdata, spc->pack_info);
10719 }
10720 
10721 NK_INTERN void
10722 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
10723  unsigned int h_oversample, unsigned int v_oversample)
10724 {
10725  NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
10726  NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
10727  if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
10728  spc->h_oversample = h_oversample;
10729  if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
10730  spc->v_oversample = v_oversample;
10731 }
10732 
10733 NK_INTERN void
10734 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10735  int kernel_width)
10736 {
10737  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10738  int safe_w = w - kernel_width;
10739  int j;
10740 
10741  for (j=0; j < h; ++j)
10742  {
10743  int i;
10744  unsigned int total;
10745  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10746 
10747  total = 0;
10748 
10749  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10750  switch (kernel_width) {
10751  case 2:
10752  for (i=0; i <= safe_w; ++i) {
10753  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10754  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10755  pixels[i] = (unsigned char) (total / 2);
10756  }
10757  break;
10758  case 3:
10759  for (i=0; i <= safe_w; ++i) {
10760  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10761  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10762  pixels[i] = (unsigned char) (total / 3);
10763  }
10764  break;
10765  case 4:
10766  for (i=0; i <= safe_w; ++i) {
10767  total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
10768  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10769  pixels[i] = (unsigned char) (total / 4);
10770  }
10771  break;
10772  case 5:
10773  for (i=0; i <= safe_w; ++i) {
10774  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10775  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10776  pixels[i] = (unsigned char) (total / 5);
10777  }
10778  break;
10779  default:
10780  for (i=0; i <= safe_w; ++i) {
10781  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10782  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10783  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10784  }
10785  break;
10786  }
10787 
10788  for (; i < w; ++i) {
10789  NK_ASSERT(pixels[i] == 0);
10790  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
10791  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10792  }
10793  pixels += stride_in_bytes;
10794  }
10795 }
10796 
10797 NK_INTERN void
10798 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10799  int kernel_width)
10800 {
10801  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10802  int safe_h = h - kernel_width;
10803  int j;
10804 
10805  for (j=0; j < w; ++j)
10806  {
10807  int i;
10808  unsigned int total;
10809  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10810 
10811  total = 0;
10812 
10813  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10814  switch (kernel_width) {
10815  case 2:
10816  for (i=0; i <= safe_h; ++i) {
10817  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10818  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10819  pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
10820  }
10821  break;
10822  case 3:
10823  for (i=0; i <= safe_h; ++i) {
10824  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10825  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10826  pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
10827  }
10828  break;
10829  case 4:
10830  for (i=0; i <= safe_h; ++i) {
10831  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10832  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10833  pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
10834  }
10835  break;
10836  case 5:
10837  for (i=0; i <= safe_h; ++i) {
10838  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10839  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10840  pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
10841  }
10842  break;
10843  default:
10844  for (i=0; i <= safe_h; ++i) {
10845  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10846  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10847  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
10848  }
10849  break;
10850  }
10851 
10852  for (; i < h; ++i) {
10853  NK_ASSERT(pixels[i*stride_in_bytes] == 0);
10854  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
10855  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
10856  }
10857  pixels += 1;
10858  }
10859 }
10860 
10861 NK_INTERN float
10862 nk_tt__oversample_shift(int oversample)
10863 {
10864  if (!oversample)
10865  return 0.0f;
10866 
10867  /* The prefilter is a box filter of width "oversample", */
10868  /* which shifts phase by (oversample - 1)/2 pixels in */
10869  /* oversampled space. We want to shift in the opposite */
10870  /* direction to counter this. */
10871  return (float)-(oversample - 1) / (2.0f * (float)oversample);
10872 }
10873 
10874 /* rects array must be big enough to accommodate all characters in the given ranges */
10875 NK_INTERN int
10876 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
10877  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
10878  int num_ranges, struct nk_rp_rect *rects)
10879 {
10880  int i,j,k;
10881  k = 0;
10882 
10883  for (i=0; i < num_ranges; ++i) {
10884  float fh = ranges[i].font_size;
10885  float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
10886  nk_tt_ScaleForMappingEmToPixels(info, -fh);
10887  ranges[i].h_oversample = (unsigned char) spc->h_oversample;
10888  ranges[i].v_oversample = (unsigned char) spc->v_oversample;
10889  for (j=0; j < ranges[i].num_chars; ++j) {
10890  int x0,y0,x1,y1;
10891  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
10892  ranges[i].first_unicode_codepoint_in_range + j :
10893  ranges[i].array_of_unicode_codepoints[j];
10894 
10895  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
10896  nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
10897  scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
10898  rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
10899  rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
10900  ++k;
10901  }
10902  }
10903  return k;
10904 }
10905 
10906 NK_INTERN int
10907 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
10908  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
10909  int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
10910 {
10911  int i,j,k, return_value = 1;
10912  /* save current values */
10913  int old_h_over = (int)spc->h_oversample;
10914  int old_v_over = (int)spc->v_oversample;
10915  /* rects array must be big enough to accommodate all characters in the given ranges */
10916 
10917  k = 0;
10918  for (i=0; i < num_ranges; ++i)
10919  {
10920  float fh = ranges[i].font_size;
10921  float recip_h,recip_v,sub_x,sub_y;
10922  float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
10923  nk_tt_ScaleForMappingEmToPixels(info, -fh);
10924 
10925  spc->h_oversample = ranges[i].h_oversample;
10926  spc->v_oversample = ranges[i].v_oversample;
10927 
10928  recip_h = 1.0f / (float)spc->h_oversample;
10929  recip_v = 1.0f / (float)spc->v_oversample;
10930 
10931  sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
10932  sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
10933 
10934  for (j=0; j < ranges[i].num_chars; ++j)
10935  {
10936  struct nk_rp_rect *r = &rects[k];
10937  if (r->was_packed)
10938  {
10939  struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
10940  int advance, lsb, x0,y0,x1,y1;
10941  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
10942  ranges[i].first_unicode_codepoint_in_range + j :
10943  ranges[i].array_of_unicode_codepoints[j];
10944  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
10945  nk_rp_coord pad = (nk_rp_coord) spc->padding;
10946 
10947  /* pad on left and top */
10948  r->x = (nk_rp_coord)((int)r->x + (int)pad);
10949  r->y = (nk_rp_coord)((int)r->y + (int)pad);
10950  r->w = (nk_rp_coord)((int)r->w - (int)pad);
10951  r->h = (nk_rp_coord)((int)r->h - (int)pad);
10952 
10953  nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
10954  nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
10955  (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
10956  nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
10957  (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
10958  spc->stride_in_bytes, scale * (float)spc->h_oversample,
10959  scale * (float)spc->v_oversample, 0,0, glyph, alloc);
10960 
10961  if (spc->h_oversample > 1)
10962  nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
10963  r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
10964 
10965  if (spc->v_oversample > 1)
10966  nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
10967  r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
10968 
10969  bc->x0 = (nk_ushort) r->x;
10970  bc->y0 = (nk_ushort) r->y;
10971  bc->x1 = (nk_ushort) (r->x + r->w);
10972  bc->y1 = (nk_ushort) (r->y + r->h);
10973  bc->xadvance = scale * (float)advance;
10974  bc->xoff = (float) x0 * recip_h + sub_x;
10975  bc->yoff = (float) y0 * recip_v + sub_y;
10976  bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x;
10977  bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y;
10978  } else {
10979  return_value = 0; /* if any fail, report failure */
10980  }
10981  ++k;
10982  }
10983  }
10984  /* restore original values */
10985  spc->h_oversample = (unsigned int)old_h_over;
10986  spc->v_oversample = (unsigned int)old_v_over;
10987  return return_value;
10988 }
10989 
10990 NK_INTERN void
10991 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
10992  int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
10993  int align_to_integer)
10994 {
10995  float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
10996  struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
10997  if (align_to_integer) {
10998  int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
10999  int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
11000 
11001  float x = (float)tx;
11002  float y = (float)ty;
11003 
11004  q->x0 = x;
11005  q->y0 = y;
11006  q->x1 = x + b->xoff2 - b->xoff;
11007  q->y1 = y + b->yoff2 - b->yoff;
11008  } else {
11009  q->x0 = *xpos + b->xoff;
11010  q->y0 = *ypos + b->yoff;
11011  q->x1 = *xpos + b->xoff2;
11012  q->y1 = *ypos + b->yoff2;
11013  }
11014  q->s0 = b->x0 * ipw;
11015  q->t0 = b->y0 * iph;
11016  q->s1 = b->x1 * ipw;
11017  q->t1 = b->y1 * iph;
11018  *xpos += b->xadvance;
11019 }
11020 
11021 /* -------------------------------------------------------------
11022  *
11023  * FONT BAKING
11024  *
11025  * --------------------------------------------------------------*/
11026 struct nk_font_bake_data {
11027  struct nk_tt_fontinfo info;
11028  struct nk_rp_rect *rects;
11029  struct nk_tt_pack_range *ranges;
11030  nk_rune range_count;
11031 };
11032 
11033 struct nk_font_baker {
11034  struct nk_allocator alloc;
11035  struct nk_tt_pack_context spc;
11036  struct nk_font_bake_data *build;
11037  struct nk_tt_packedchar *packed_chars;
11038  struct nk_rp_rect *rects;
11039  struct nk_tt_pack_range *ranges;
11040 };
11041 
11042 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
11043 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
11044 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
11045 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
11046 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
11047 
11048 NK_INTERN int
11049 nk_range_count(const nk_rune *range)
11050 {
11051  const nk_rune *iter = range;
11052  NK_ASSERT(range);
11053  if (!range) return 0;
11054  while (*(iter++) != 0);
11055  return (iter == range) ? 0 : (int)((iter - range)/2);
11056 }
11057 
11058 NK_INTERN int
11059 nk_range_glyph_count(const nk_rune *range, int count)
11060 {
11061  int i = 0;
11062  int total_glyphs = 0;
11063  for (i = 0; i < count; ++i) {
11064  int diff;
11065  nk_rune f = range[(i*2)+0];
11066  nk_rune t = range[(i*2)+1];
11067  NK_ASSERT(t >= f);
11068  diff = (int)((t - f) + 1);
11069  total_glyphs += diff;
11070  }
11071  return total_glyphs;
11072 }
11073 
11074 NK_API const nk_rune*
11075 nk_font_default_glyph_ranges(void)
11076 {
11077  NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
11078  return ranges;
11079 }
11080 
11081 NK_API const nk_rune*
11082 nk_font_chinese_glyph_ranges(void)
11083 {
11084  NK_STORAGE const nk_rune ranges[] = {
11085  0x0020, 0x00FF,
11086  0x3000, 0x30FF,
11087  0x31F0, 0x31FF,
11088  0xFF00, 0xFFEF,
11089  0x4e00, 0x9FAF,
11090  0
11091  };
11092  return ranges;
11093 }
11094 
11095 NK_API const nk_rune*
11096 nk_font_cyrillic_glyph_ranges(void)
11097 {
11098  NK_STORAGE const nk_rune ranges[] = {
11099  0x0020, 0x00FF,
11100  0x0400, 0x052F,
11101  0x2DE0, 0x2DFF,
11102  0xA640, 0xA69F,
11103  0
11104  };
11105  return ranges;
11106 }
11107 
11108 NK_API const nk_rune*
11109 nk_font_korean_glyph_ranges(void)
11110 {
11111  NK_STORAGE const nk_rune ranges[] = {
11112  0x0020, 0x00FF,
11113  0x3131, 0x3163,
11114  0xAC00, 0xD79D,
11115  0
11116  };
11117  return ranges;
11118 }
11119 
11120 NK_INTERN void
11121 nk_font_baker_memory(nk_size *temp, int *glyph_count,
11122  struct nk_font_config *config_list, int count)
11123 {
11124  int range_count = 0;
11125  int total_range_count = 0;
11126  struct nk_font_config *iter;
11127 
11128  NK_ASSERT(config_list);
11129  NK_ASSERT(glyph_count);
11130  if (!config_list) {
11131  *temp = 0;
11132  *glyph_count = 0;
11133  return;
11134  }
11135 
11136  *glyph_count = 0;
11137  if (!config_list->range)
11138  config_list->range = nk_font_default_glyph_ranges();
11139  for (iter = config_list; iter; iter = iter->next) {
11140  range_count = nk_range_count(iter->range);
11141  total_range_count += range_count;
11142  *glyph_count += nk_range_glyph_count(iter->range, range_count);
11143  }
11144 
11145  *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
11146  *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
11147  *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
11148  *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
11149  *temp += sizeof(struct nk_font_baker);
11150  *temp += nk_rect_align + nk_range_align + nk_char_align;
11151  *temp += nk_build_align + nk_baker_align;
11152 }
11153 
11154 NK_INTERN struct nk_font_baker*
11155 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
11156 {
11157  struct nk_font_baker *baker;
11158  if (!memory) return 0;
11159  /* setup baker inside a memory block */
11160  baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
11161  baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
11162  baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
11163  baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
11164  baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
11165  baker->alloc = *alloc;
11166  return baker;
11167 }
11168 
11169 NK_INTERN int
11170 nk_font_bake_pack(struct nk_font_baker *baker,
11171  nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
11172  const struct nk_font_config *config_list, int count,
11173  struct nk_allocator *alloc)
11174 {
11175  NK_STORAGE const nk_size max_height = 1024 * 32;
11176  const struct nk_font_config *config_iter;
11177  int total_glyph_count = 0;
11178  int total_range_count = 0;
11179  int range_count = 0;
11180  int i = 0;
11181 
11182  NK_ASSERT(image_memory);
11183  NK_ASSERT(width);
11184  NK_ASSERT(height);
11185  NK_ASSERT(config_list);
11186  NK_ASSERT(count);
11187  NK_ASSERT(alloc);
11188 
11189  if (!image_memory || !width || !height || !config_list || !count) return nk_false;
11190  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11191  range_count = nk_range_count(config_iter->range);
11192  total_range_count += range_count;
11193  total_glyph_count += nk_range_glyph_count(config_iter->range, range_count);
11194  }
11195 
11196  /* setup font baker from temporary memory */
11197  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11198  const struct nk_font_config *cfg = config_iter;
11199  if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)cfg->ttf_blob, 0))
11200  return nk_false;
11201  }
11202 
11203  *height = 0;
11204  *width = (total_glyph_count > 1000) ? 1024 : 512;
11205  nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
11206  {
11207  int input_i = 0;
11208  int range_n = 0;
11209  int rect_n = 0;
11210  int char_n = 0;
11211 
11212  if (custom) {
11213  /* pack custom user data first so it will be in the upper left corner*/
11214  struct nk_rp_rect custom_space;
11215  nk_zero(&custom_space, sizeof(custom_space));
11216  custom_space.w = (nk_rp_coord)((custom->w * 2) + 1);
11217  custom_space.h = (nk_rp_coord)(custom->h + 1);
11218 
11219  nk_tt_PackSetOversampling(&baker->spc, 1, 1);
11220  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
11221  *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
11222 
11223  custom->x = (short)custom_space.x;
11224  custom->y = (short)custom_space.y;
11225  custom->w = (short)custom_space.w;
11226  custom->h = (short)custom_space.h;
11227  }
11228 
11229  /* first font pass: pack all glyphs */
11230  for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
11231  input_i++, config_iter = config_iter->next)
11232  {
11233  int n = 0;
11234  int glyph_count;
11235  const nk_rune *in_range;
11236  const struct nk_font_config *cfg = config_iter;
11237  struct nk_font_bake_data *tmp = &baker->build[input_i];
11238 
11239  /* count glyphs + ranges in current font */
11240  glyph_count = 0; range_count = 0;
11241  for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
11242  glyph_count += (int)(in_range[1] - in_range[0]) + 1;
11243  range_count++;
11244  }
11245 
11246  /* setup ranges */
11247  tmp->ranges = baker->ranges + range_n;
11248  tmp->range_count = (nk_rune)range_count;
11249  range_n += range_count;
11250  for (i = 0; i < range_count; ++i) {
11251  in_range = &cfg->range[i * 2];
11252  tmp->ranges[i].font_size = cfg->size;
11253  tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
11254  tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
11255  tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
11256  char_n += tmp->ranges[i].num_chars;
11257  }
11258 
11259  /* pack */
11260  tmp->rects = baker->rects + rect_n;
11261  rect_n += glyph_count;
11262  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11263  n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
11264  tmp->ranges, (int)tmp->range_count, tmp->rects);
11265  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
11266 
11267  /* texture height */
11268  for (i = 0; i < n; ++i) {
11269  if (tmp->rects[i].was_packed)
11270  *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
11271  }
11272  }
11273  NK_ASSERT(rect_n == total_glyph_count);
11274  NK_ASSERT(char_n == total_glyph_count);
11275  NK_ASSERT(range_n == total_range_count);
11276  }
11277  *height = (int)nk_round_up_pow2((nk_uint)*height);
11278  *image_memory = (nk_size)(*width) * (nk_size)(*height);
11279  return nk_true;
11280 }
11281 
11282 NK_INTERN void
11283 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
11284  struct nk_font_glyph *glyphs, int glyphs_count,
11285  const struct nk_font_config *config_list, int font_count)
11286 {
11287  int input_i = 0;
11288  nk_rune glyph_n = 0;
11289  const struct nk_font_config *config_iter;
11290 
11291  NK_ASSERT(image_memory);
11292  NK_ASSERT(width);
11293  NK_ASSERT(height);
11294  NK_ASSERT(config_list);
11295  NK_ASSERT(baker);
11296  NK_ASSERT(font_count);
11297  NK_ASSERT(glyphs_count);
11298  if (!image_memory || !width || !height || !config_list ||
11299  !font_count || !glyphs || !glyphs_count)
11300  return;
11301 
11302  /* second font pass: render glyphs */
11303  nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
11304  baker->spc.pixels = (unsigned char*)image_memory;
11305  baker->spc.height = (int)height;
11306  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11307  ++input_i, config_iter = config_iter->next)
11308  {
11309  const struct nk_font_config *cfg = config_iter;
11310  struct nk_font_bake_data *tmp = &baker->build[input_i];
11311  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11312  nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
11313  (int)tmp->range_count, tmp->rects, &baker->alloc);
11314  }
11315  nk_tt_PackEnd(&baker->spc, &baker->alloc);
11316 
11317  /* third pass: setup font and glyphs */
11318  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11319  ++input_i, config_iter = config_iter->next)
11320  {
11321  nk_size i = 0;
11322  int char_idx = 0;
11323  nk_rune glyph_count = 0;
11324  const struct nk_font_config *cfg = config_iter;
11325  struct nk_font_bake_data *tmp = &baker->build[input_i];
11326  struct nk_baked_font *dst_font = cfg->font;
11327 
11328  float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
11329  int unscaled_ascent, unscaled_descent, unscaled_line_gap;
11330  nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
11331  &unscaled_line_gap);
11332 
11333  /* fill baked font */
11334  if (!cfg->merge_mode) {
11335  dst_font->ranges = cfg->range;
11336  dst_font->height = cfg->size;
11337  dst_font->ascent = ((float)unscaled_ascent * font_scale);
11338  dst_font->descent = ((float)unscaled_descent * font_scale);
11339  dst_font->glyph_offset = glyph_n;
11340  }
11341 
11342  /* fill own baked font glyph array */
11343  for (i = 0; i < tmp->range_count; ++i)
11344  {
11345  struct nk_tt_pack_range *range = &tmp->ranges[i];
11346  for (char_idx = 0; char_idx < range->num_chars; char_idx++)
11347  {
11348  nk_rune codepoint = 0;
11349  float dummy_x = 0, dummy_y = 0;
11350  struct nk_tt_aligned_quad q;
11351  struct nk_font_glyph *glyph;
11352 
11353  /* query glyph bounds from stb_truetype */
11354  const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
11355  if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
11356  codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
11357  nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
11358  (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
11359 
11360  /* fill own glyph type with data */
11361  glyph = &glyphs[dst_font->glyph_offset + (unsigned int)glyph_count];
11362  glyph->codepoint = codepoint;
11363  glyph->x0 = q.x0; glyph->y0 = q.y0;
11364  glyph->x1 = q.x1; glyph->y1 = q.y1;
11365  glyph->y0 += (dst_font->ascent + 0.5f);
11366  glyph->y1 += (dst_font->ascent + 0.5f);
11367  glyph->w = glyph->x1 - glyph->x0 + 0.5f;
11368  glyph->h = glyph->y1 - glyph->y0;
11369 
11370  if (cfg->coord_type == NK_COORD_PIXEL) {
11371  glyph->u0 = q.s0 * (float)width;
11372  glyph->v0 = q.t0 * (float)height;
11373  glyph->u1 = q.s1 * (float)width;
11374  glyph->v1 = q.t1 * (float)height;
11375  } else {
11376  glyph->u0 = q.s0;
11377  glyph->v0 = q.t0;
11378  glyph->u1 = q.s1;
11379  glyph->v1 = q.t1;
11380  }
11381  glyph->xadvance = (pc->xadvance + cfg->spacing.x);
11382  if (cfg->pixel_snap)
11383  glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
11384  glyph_count++;
11385  }
11386  }
11387  dst_font->glyph_count = glyph_count;
11388  glyph_n += dst_font->glyph_count;
11389  }
11390 }
11391 
11392 NK_INTERN void
11393 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
11394  struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
11395  int tex_height, char white, char black)
11396 {
11397  nk_byte *pixels;
11398  int y = 0;
11399  int x = 0;
11400  int n = 0;
11401 
11402  NK_ASSERT(img_memory);
11403  NK_ASSERT(img_width);
11404  NK_ASSERT(img_height);
11405  NK_ASSERT(texture_data_mask);
11406  NK_UNUSED(tex_height);
11407  if (!img_memory || !img_width || !img_height || !texture_data_mask)
11408  return;
11409 
11410  pixels = (nk_byte*)img_memory;
11411  for (y = 0, n = 0; y < tex_height; ++y) {
11412  for (x = 0; x < tex_width; ++x, ++n) {
11413  const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
11414  const int off1 = off0 + 1 + tex_width;
11415  pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
11416  pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
11417  }
11418  }
11419 }
11420 
11421 NK_INTERN void
11422 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
11423  const void *in_memory)
11424 {
11425  int n = 0;
11426  nk_rune *dst;
11427  const nk_byte *src;
11428 
11429  NK_ASSERT(out_memory);
11430  NK_ASSERT(in_memory);
11431  NK_ASSERT(img_width);
11432  NK_ASSERT(img_height);
11433  if (!out_memory || !in_memory || !img_height || !img_width) return;
11434 
11435  dst = (nk_rune*)out_memory;
11436  src = (const nk_byte*)in_memory;
11437  for (n = (int)(img_width * img_height); n > 0; n--)
11438  *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
11439 }
11440 
11441 /* -------------------------------------------------------------
11442  *
11443  * FONT
11444  *
11445  * --------------------------------------------------------------*/
11446 NK_INTERN float
11447 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
11448 {
11449  nk_rune unicode;
11450  int text_len = 0;
11451  float text_width = 0;
11452  int glyph_len = 0;
11453  float scale = 0;
11454 
11455  struct nk_font *font = (struct nk_font*)handle.ptr;
11456  NK_ASSERT(font);
11457  NK_ASSERT(font->glyphs);
11458  if (!font || !text || !len)
11459  return 0;
11460 
11461  scale = height/font->info.height;
11462  glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
11463  if (!glyph_len) return 0;
11464  while (text_len <= (int)len && glyph_len) {
11465  const struct nk_font_glyph *g;
11466  if (unicode == NK_UTF_INVALID) break;
11467 
11468  /* query currently drawn glyph information */
11469  g = nk_font_find_glyph(font, unicode);
11470  text_width += g->xadvance * scale;
11471 
11472  /* offset next glyph */
11473  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
11474  text_len += glyph_len;
11475  }
11476  return text_width;
11477 }
11478 
11479 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11480 NK_INTERN void
11481 nk_font_query_font_glyph(nk_handle handle, float height,
11482  struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
11483 {
11484  float scale;
11485  const struct nk_font_glyph *g;
11486  struct nk_font *font;
11487 
11488  NK_ASSERT(glyph);
11489  NK_UNUSED(next_codepoint);
11490 
11491  font = (struct nk_font*)handle.ptr;
11492  NK_ASSERT(font);
11493  NK_ASSERT(font->glyphs);
11494  if (!font || !glyph)
11495  return;
11496 
11497  scale = height/font->info.height;
11498  g = nk_font_find_glyph(font, codepoint);
11499  glyph->width = (g->x1 - g->x0) * scale;
11500  glyph->height = (g->y1 - g->y0) * scale;
11501  glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
11502  glyph->xadvance = (g->xadvance * scale);
11503  glyph->uv[0] = nk_vec2(g->u0, g->v0);
11504  glyph->uv[1] = nk_vec2(g->u1, g->v1);
11505 }
11506 #endif
11507 
11508 NK_API const struct nk_font_glyph*
11509 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
11510 {
11511  int i = 0;
11512  int count;
11513  int total_glyphs = 0;
11514  const struct nk_font_glyph *glyph = 0;
11515 
11516  NK_ASSERT(font);
11517  NK_ASSERT(font->glyphs);
11518  NK_ASSERT(font->info.ranges);
11519  if (!font || !font->glyphs) return 0;
11520 
11521  glyph = font->fallback;
11522  count = nk_range_count(font->info.ranges);
11523  for (i = 0; i < count; ++i) {
11524  int diff;
11525  nk_rune f = font->info.ranges[(i*2)+0];
11526  nk_rune t = font->info.ranges[(i*2)+1];
11527  diff = (int)((t - f) + 1);
11528  if (unicode >= f && unicode <= t)
11529  return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
11530  total_glyphs += diff;
11531  }
11532  return glyph;
11533 }
11534 
11535 NK_INTERN void
11536 nk_font_init(struct nk_font *font, float pixel_height,
11537  nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
11538  const struct nk_baked_font *baked_font, nk_handle atlas)
11539 {
11540  struct nk_baked_font baked;
11541  NK_ASSERT(font);
11542  NK_ASSERT(glyphs);
11543  NK_ASSERT(baked_font);
11544  if (!font || !glyphs || !baked_font)
11545  return;
11546 
11547  baked = *baked_font;
11548  font->info = baked;
11549  font->scale = (float)pixel_height / (float)font->info.height;
11550  font->glyphs = &glyphs[baked_font->glyph_offset];
11551  font->texture = atlas;
11552  font->fallback_codepoint = fallback_codepoint;
11553  font->fallback = nk_font_find_glyph(font, fallback_codepoint);
11554 
11555  font->handle.height = font->info.height * font->scale;
11556  font->handle.width = nk_font_text_width;
11557  font->handle.userdata.ptr = font;
11558 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11559  font->handle.query = nk_font_query_font_glyph;
11560  font->handle.texture = font->texture;
11561 #endif
11562 }
11563 
11564 /* ---------------------------------------------------------------------------
11565  *
11566  * DEFAULT FONT
11567  *
11568  * ProggyClean.ttf
11569  * Copyright (c) 2004, 2005 Tristan Grimmer
11570  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
11571  * Download and more information at http://upperbounds.net
11572  *-----------------------------------------------------------------------------*/
11573 #ifdef NK_INCLUDE_DEFAULT_FONT
11574 
11575  #ifdef __clang__
11576 #pragma clang diagnostic push
11577 
11578 #pragma clang diagnostic ignored "-Woverlength-strings"
11579 #elif defined(__GNUC__) || defined(__GNUG__)
11580 #pragma GCC diagnostic push
11581 #pragma GCC diagnostic ignored "-Woverlength-strings"
11582 #endif
11583 
11584 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
11585  "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
11586  "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
11587  "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
11588  "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
11589  "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
11590  "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
11591  "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
11592  "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
11593  "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
11594  "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
11595  "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
11596  "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
11597  "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
11598  "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
11599  "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
11600  "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
11601  "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
11602  "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
11603  "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
11604  "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
11605  "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
11606  "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
11607  "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
11608  "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
11609  "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
11610  "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
11611  "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
11612  "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
11613  "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
11614  "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
11615  ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
11616  "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
11617  "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
11618  "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
11619  "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
11620  "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
11621  "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
11622  ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
11623  "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
11624  "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
11625  "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
11626  "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
11627  "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
11628  "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
11629  "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
11630  "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
11631  ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
11632  "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
11633  "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
11634  ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
11635  "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
11636  "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
11637  "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
11638  ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
11639  "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
11640  "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
11641  "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
11642  "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
11643  "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
11644  "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
11645  "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
11646  "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
11647  "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
11648  "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
11649  "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
11650  "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
11651  "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
11652  "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
11653  ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
11654  "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
11655  "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
11656  "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
11657  "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
11658  "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
11659  "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
11660  "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
11661  "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
11662  ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
11663  "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
11664  "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
11665  "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
11666  "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
11667  "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
11668  "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
11669  "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
11670  "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
11671 #endif /* NK_INCLUDE_DEFAULT_FONT */
11672 
11673 #define NK_CURSOR_DATA_W 90
11674 #define NK_CURSOR_DATA_H 27
11675 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
11676 {
11677  "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX"
11678  "..- -X.....X- X.X - X.X -X.....X - X.....X"
11679  "--- -XXX.XXX- X...X - X...X -X....X - X....X"
11680  "X - X.X - X.....X - X.....X -X...X - X...X"
11681  "XX - X.X -X.......X- X.......X -X..X.X - X.X..X"
11682  "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X"
11683  "X..X - X.X - X.X - X.X -XX X.X - X.X XX"
11684  "X...X - X.X - X.X - XX X.X XX - X.X - X.X "
11685  "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X "
11686  "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X "
11687  "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X "
11688  "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X "
11689  "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X "
11690  "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X "
11691  "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X "
11692  "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X "
11693  "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX "
11694  "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------"
11695  "X.X X..X - -X.......X- X.......X - XX XX - "
11696  "XX X..X - - X.....X - X.....X - X.X X.X - "
11697  " X..X - X...X - X...X - X..X X..X - "
11698  " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - "
11699  "------------ - X - X -X.....................X- "
11700  " ----------------------------------- X...XXXXXXXXXXXXX...X - "
11701  " - X..X X..X - "
11702  " - X.X X.X - "
11703  " - XX XX - "
11704 };
11705 
11706 #ifdef __clang__
11707 #pragma clang diagnostic pop
11708 #elif defined(__GNUC__) || defined(__GNUG__)
11709 #pragma GCC diagnostic pop
11710 #endif
11711 
11712 NK_INTERN unsigned int
11713 nk_decompress_length(unsigned char *input)
11714 {
11715  return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
11716 }
11717 
11718 NK_GLOBAL unsigned char *nk__barrier;
11719 NK_GLOBAL unsigned char *nk__barrier2;
11720 NK_GLOBAL unsigned char *nk__barrier3;
11721 NK_GLOBAL unsigned char *nk__barrier4;
11722 NK_GLOBAL unsigned char *nk__dout;
11723 
11724 NK_INTERN void
11725 nk__match(unsigned char *data, unsigned int length)
11726 {
11727  /* INVERSE of memmove... write each byte before copying the next...*/
11728  NK_ASSERT (nk__dout + length <= nk__barrier);
11729  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11730  if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
11731  while (length--) *nk__dout++ = *data++;
11732 }
11733 
11734 NK_INTERN void
11735 nk__lit(unsigned char *data, unsigned int length)
11736 {
11737  NK_ASSERT (nk__dout + length <= nk__barrier);
11738  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11739  if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
11740  NK_MEMCPY(nk__dout, data, length);
11741  nk__dout += length;
11742 }
11743 
11744 #define nk__in2(x) ((i[x] << 8) + i[(x)+1])
11745 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1))
11746 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1))
11747 
11748 NK_INTERN unsigned char*
11749 nk_decompress_token(unsigned char *i)
11750 {
11751  if (*i >= 0x20) { /* use fewer if's for cases that expand small */
11752  if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
11753  else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
11754  else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
11755  } else { /* more ifs for cases that expand large, since overhead is amortized */
11756  if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
11757  else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
11758  else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
11759  else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
11760  else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
11761  else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
11762  }
11763  return i;
11764 }
11765 
11766 NK_INTERN unsigned int
11767 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
11768 {
11769  const unsigned long ADLER_MOD = 65521;
11770  unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
11771  unsigned long blocklen, i;
11772 
11773  blocklen = buflen % 5552;
11774  while (buflen) {
11775  for (i=0; i + 7 < blocklen; i += 8) {
11776  s1 += buffer[0]; s2 += s1;
11777  s1 += buffer[1]; s2 += s1;
11778  s1 += buffer[2]; s2 += s1;
11779  s1 += buffer[3]; s2 += s1;
11780  s1 += buffer[4]; s2 += s1;
11781  s1 += buffer[5]; s2 += s1;
11782  s1 += buffer[6]; s2 += s1;
11783  s1 += buffer[7]; s2 += s1;
11784  buffer += 8;
11785  }
11786  for (; i < blocklen; ++i) {
11787  s1 += *buffer++; s2 += s1;
11788  }
11789 
11790  s1 %= ADLER_MOD; s2 %= ADLER_MOD;
11791  buflen -= (unsigned int)blocklen;
11792  blocklen = 5552;
11793  }
11794  return (unsigned int)(s2 << 16) + (unsigned int)s1;
11795 }
11796 
11797 NK_INTERN unsigned int
11798 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
11799 {
11800  unsigned int olen;
11801  if (nk__in4(0) != 0x57bC0000) return 0;
11802  if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */
11803  olen = nk_decompress_length(i);
11804  nk__barrier2 = i;
11805  nk__barrier3 = i+length;
11806  nk__barrier = output + olen;
11807  nk__barrier4 = output;
11808  i += 16;
11809 
11810  nk__dout = output;
11811  for (;;) {
11812  unsigned char *old_i = i;
11813  i = nk_decompress_token(i);
11814  if (i == old_i) {
11815  if (*i == 0x05 && i[1] == 0xfa) {
11816  NK_ASSERT(nk__dout == output + olen);
11817  if (nk__dout != output + olen) return 0;
11818  if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
11819  return 0;
11820  return olen;
11821  } else {
11822  NK_ASSERT(0); /* NOTREACHED */
11823  return 0;
11824  }
11825  }
11826  NK_ASSERT(nk__dout <= output + olen);
11827  if (nk__dout > output + olen)
11828  return 0;
11829  }
11830 }
11831 
11832 NK_INTERN unsigned int
11833 nk_decode_85_byte(char c)
11834 { return (unsigned int)((c >= '\\') ? c-36 : c-35); }
11835 
11836 NK_INTERN void
11837 nk_decode_85(unsigned char* dst, const unsigned char* src)
11838 {
11839  while (*src)
11840  {
11841  unsigned int tmp =
11842  nk_decode_85_byte((char)src[0]) +
11843  85 * (nk_decode_85_byte((char)src[1]) +
11844  85 * (nk_decode_85_byte((char)src[2]) +
11845  85 * (nk_decode_85_byte((char)src[3]) +
11846  85 * nk_decode_85_byte((char)src[4]))));
11847 
11848  /* we can't assume little-endianess. */
11849  dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
11850  dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
11851  dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
11852  dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
11853 
11854  src += 5;
11855  dst += 4;
11856  }
11857 }
11858 
11859 /* -------------------------------------------------------------
11860  *
11861  * FONT ATLAS
11862  *
11863  * --------------------------------------------------------------*/
11864 NK_API struct nk_font_config
11865 nk_font_config(float pixel_height)
11866 {
11867  struct nk_font_config cfg;
11868  nk_zero_struct(cfg);
11869  cfg.ttf_blob = 0;
11870  cfg.ttf_size = 0;
11871  cfg.ttf_data_owned_by_atlas = 0;
11872  cfg.size = pixel_height;
11873  cfg.oversample_h = 3;
11874  cfg.oversample_v = 1;
11875  cfg.pixel_snap = 0;
11876  cfg.coord_type = NK_COORD_UV;
11877  cfg.spacing = nk_vec2(0,0);
11878  cfg.range = nk_font_default_glyph_ranges();
11879  cfg.merge_mode = 0;
11880  cfg.fallback_glyph = '?';
11881  cfg.font = 0;
11882  return cfg;
11883 }
11884 
11885 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
11886 NK_API void
11887 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
11888 {
11889  NK_ASSERT(atlas);
11890  if (!atlas) return;
11891  nk_zero_struct(*atlas);
11892  atlas->temporary.userdata.ptr = 0;
11893  atlas->temporary.alloc = nk_malloc;
11894  atlas->temporary.free = nk_mfree;
11895  atlas->permanent.userdata.ptr = 0;
11896  atlas->permanent.alloc = nk_malloc;
11897  atlas->permanent.free = nk_mfree;
11898 }
11899 #endif
11900 
11901 NK_API void
11902 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
11903 {
11904  NK_ASSERT(atlas);
11905  NK_ASSERT(alloc);
11906  if (!atlas || !alloc) return;
11907  nk_zero_struct(*atlas);
11908  atlas->permanent = *alloc;
11909  atlas->temporary = *alloc;
11910 }
11911 
11912 NK_API void
11913 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
11914  struct nk_allocator *permanent, struct nk_allocator *temporary)
11915 {
11916  NK_ASSERT(atlas);
11917  NK_ASSERT(permanent);
11918  NK_ASSERT(temporary);
11919  if (!atlas || !permanent || !temporary) return;
11920  nk_zero_struct(*atlas);
11921  atlas->permanent = *permanent;
11922  atlas->temporary = *temporary;
11923 }
11924 
11925 NK_API void
11926 nk_font_atlas_begin(struct nk_font_atlas *atlas)
11927 {
11928  NK_ASSERT(atlas);
11929  NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
11930  NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
11931  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
11932  !atlas->temporary.alloc || !atlas->temporary.free) return;
11933  if (atlas->glyphs) {
11934  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
11935  atlas->glyphs = 0;
11936  }
11937  if (atlas->pixel) {
11938  atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
11939  atlas->pixel = 0;
11940  }
11941 }
11942 
11943 NK_API struct nk_font*
11944 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
11945 {
11946  struct nk_font *font = 0;
11947  struct nk_font_config *cfg;
11948 
11949  NK_ASSERT(atlas);
11950  NK_ASSERT(atlas->permanent.alloc);
11951  NK_ASSERT(atlas->permanent.free);
11952  NK_ASSERT(atlas->temporary.alloc);
11953  NK_ASSERT(atlas->temporary.free);
11954 
11955  NK_ASSERT(config);
11956  NK_ASSERT(config->ttf_blob);
11957  NK_ASSERT(config->ttf_size);
11958  NK_ASSERT(config->size > 0.0f);
11959 
11960  if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
11961  !atlas->permanent.alloc || !atlas->permanent.free ||
11962  !atlas->temporary.alloc || !atlas->temporary.free)
11963  return 0;
11964 
11965  /* allocate and insert font config into list */
11966  cfg = (struct nk_font_config*)
11967  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
11968  NK_MEMCPY(cfg, config, sizeof(*config));
11969  if (!atlas->config) {
11970  atlas->config = cfg;
11971  cfg->next = 0;
11972  } else {
11973  cfg->next = atlas->config;
11974  atlas->config = cfg;
11975  }
11976 
11977  /* allocate new font */
11978  if (!config->merge_mode) {
11979  font = (struct nk_font*)
11980  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
11981  NK_ASSERT(font);
11982  if (!font) return 0;
11983  font->config = cfg;
11984  } else {
11985  NK_ASSERT(atlas->font_num);
11986  font = atlas->fonts;
11987  font->config = cfg;
11988  }
11989 
11990  /* insert font into list */
11991  if (!config->merge_mode) {
11992  if (!atlas->fonts) {
11993  atlas->fonts = font;
11994  font->next = 0;
11995  } else {
11996  font->next = atlas->fonts;
11997  atlas->fonts = font;
11998  }
11999  cfg->font = &font->info;
12000  }
12001 
12002  /* create own copy of .TTF font blob */
12003  if (!config->ttf_data_owned_by_atlas) {
12004  cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
12005  NK_ASSERT(cfg->ttf_blob);
12006  if (!cfg->ttf_blob) {
12007  atlas->font_num++;
12008  return 0;
12009  }
12010  NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
12011  cfg->ttf_data_owned_by_atlas = 1;
12012  }
12013  atlas->font_num++;
12014  return font;
12015 }
12016 
12017 NK_API struct nk_font*
12018 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
12019  nk_size size, float height, const struct nk_font_config *config)
12020 {
12021  struct nk_font_config cfg;
12022  NK_ASSERT(memory);
12023  NK_ASSERT(size);
12024 
12025  NK_ASSERT(atlas);
12026  NK_ASSERT(atlas->temporary.alloc);
12027  NK_ASSERT(atlas->temporary.free);
12028  NK_ASSERT(atlas->permanent.alloc);
12029  NK_ASSERT(atlas->permanent.free);
12030  if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
12031  !atlas->permanent.alloc || !atlas->permanent.free)
12032  return 0;
12033 
12034  cfg = (config) ? *config: nk_font_config(height);
12035  cfg.ttf_blob = memory;
12036  cfg.ttf_size = size;
12037  cfg.size = height;
12038  cfg.ttf_data_owned_by_atlas = 0;
12039  return nk_font_atlas_add(atlas, &cfg);
12040 }
12041 
12042 #ifdef NK_INCLUDE_STANDARD_IO
12043 NK_API struct nk_font*
12044 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
12045  float height, const struct nk_font_config *config)
12046 {
12047  nk_size size;
12048  char *memory;
12049  struct nk_font_config cfg;
12050 
12051  NK_ASSERT(atlas);
12052  NK_ASSERT(atlas->temporary.alloc);
12053  NK_ASSERT(atlas->temporary.free);
12054  NK_ASSERT(atlas->permanent.alloc);
12055  NK_ASSERT(atlas->permanent.free);
12056 
12057  if (!atlas || !file_path) return 0;
12058  memory = nk_file_load(file_path, &size, &atlas->permanent);
12059  if (!memory) return 0;
12060 
12061  cfg = (config) ? *config: nk_font_config(height);
12062  cfg.ttf_blob = memory;
12063  cfg.ttf_size = size;
12064  cfg.size = height;
12065  cfg.ttf_data_owned_by_atlas = 1;
12066  return nk_font_atlas_add(atlas, &cfg);
12067 }
12068 #endif
12069 
12070 NK_API struct nk_font*
12071 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
12072  void *compressed_data, nk_size compressed_size, float height,
12073  const struct nk_font_config *config)
12074 {
12075  unsigned int decompressed_size;
12076  void *decompressed_data;
12077  struct nk_font_config cfg;
12078 
12079  NK_ASSERT(atlas);
12080  NK_ASSERT(atlas->temporary.alloc);
12081  NK_ASSERT(atlas->temporary.free);
12082  NK_ASSERT(atlas->permanent.alloc);
12083  NK_ASSERT(atlas->permanent.free);
12084 
12085  NK_ASSERT(compressed_data);
12086  NK_ASSERT(compressed_size);
12087  if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
12088  !atlas->permanent.alloc || !atlas->permanent.free)
12089  return 0;
12090 
12091  decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
12092  decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
12093  NK_ASSERT(decompressed_data);
12094  if (!decompressed_data) return 0;
12095  nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
12096  (unsigned int)compressed_size);
12097 
12098  cfg = (config) ? *config: nk_font_config(height);
12099  cfg.ttf_blob = decompressed_data;
12100  cfg.ttf_size = decompressed_size;
12101  cfg.size = height;
12102  cfg.ttf_data_owned_by_atlas = 1;
12103  return nk_font_atlas_add(atlas, &cfg);
12104 }
12105 
12106 NK_API struct nk_font*
12107 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
12108  const char *data_base85, float height, const struct nk_font_config *config)
12109 {
12110  int compressed_size;
12111  void *compressed_data;
12112  struct nk_font *font;
12113 
12114  NK_ASSERT(atlas);
12115  NK_ASSERT(atlas->temporary.alloc);
12116  NK_ASSERT(atlas->temporary.free);
12117  NK_ASSERT(atlas->permanent.alloc);
12118  NK_ASSERT(atlas->permanent.free);
12119 
12120  NK_ASSERT(data_base85);
12121  if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
12122  !atlas->permanent.alloc || !atlas->permanent.free)
12123  return 0;
12124 
12125  compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
12126  compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
12127  NK_ASSERT(compressed_data);
12128  if (!compressed_data) return 0;
12129  nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
12130  font = nk_font_atlas_add_compressed(atlas, compressed_data,
12131  (nk_size)compressed_size, height, config);
12132  atlas->temporary.free(atlas->temporary.userdata, compressed_data);
12133  return font;
12134 }
12135 
12136 #ifdef NK_INCLUDE_DEFAULT_FONT
12137 NK_API struct nk_font*
12138 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
12139  float pixel_height, const struct nk_font_config *config)
12140 {
12141  NK_ASSERT(atlas);
12142  NK_ASSERT(atlas->temporary.alloc);
12143  NK_ASSERT(atlas->temporary.free);
12144  NK_ASSERT(atlas->permanent.alloc);
12145  NK_ASSERT(atlas->permanent.free);
12146  return nk_font_atlas_add_compressed_base85(atlas,
12147  nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
12148 }
12149 #endif
12150 
12151 NK_API const void*
12152 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
12153  enum nk_font_atlas_format fmt)
12154 {
12155  int i = 0;
12156  void *tmp = 0;
12157  nk_size tmp_size, img_size;
12158  struct nk_font *font_iter;
12159  struct nk_font_baker *baker;
12160 
12161  NK_ASSERT(atlas);
12162  NK_ASSERT(atlas->temporary.alloc);
12163  NK_ASSERT(atlas->temporary.free);
12164  NK_ASSERT(atlas->permanent.alloc);
12165  NK_ASSERT(atlas->permanent.free);
12166 
12167  NK_ASSERT(width);
12168  NK_ASSERT(height);
12169  if (!atlas || !width || !height ||
12170  !atlas->temporary.alloc || !atlas->temporary.free ||
12171  !atlas->permanent.alloc || !atlas->permanent.free)
12172  return 0;
12173 
12174 #ifdef NK_INCLUDE_DEFAULT_FONT
12175  /* no font added so just use default font */
12176  if (!atlas->font_num)
12177  atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
12178 #endif
12179  NK_ASSERT(atlas->font_num);
12180  if (!atlas->font_num) return 0;
12181 
12182  /* allocate temporary baker memory required for the baking process */
12183  nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
12184  tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
12185  NK_ASSERT(tmp);
12186  if (!tmp) goto failed;
12187 
12188  /* allocate glyph memory for all fonts */
12189  baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
12190  atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
12191  atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
12192  NK_ASSERT(atlas->glyphs);
12193  if (!atlas->glyphs)
12194  goto failed;
12195 
12196  /* pack all glyphs into a tight fit space */
12197  atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
12198  atlas->custom.h = NK_CURSOR_DATA_H + 1;
12199  if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
12200  atlas->config, atlas->font_num, &atlas->temporary))
12201  goto failed;
12202 
12203  /* allocate memory for the baked image font atlas */
12204  atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
12205  NK_ASSERT(atlas->pixel);
12206  if (!atlas->pixel)
12207  goto failed;
12208 
12209  /* bake glyphs and custom white pixel into image */
12210  nk_font_bake(baker, atlas->pixel, *width, *height,
12211  atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
12212  nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
12213  nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
12214 
12215  if (fmt == NK_FONT_ATLAS_RGBA32) {
12216  /* convert alpha8 image into rgba32 image */
12217  void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
12218  (nk_size)(*width * *height * 4));
12219  NK_ASSERT(img_rgba);
12220  if (!img_rgba) goto failed;
12221  nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
12222  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12223  atlas->pixel = img_rgba;
12224  }
12225  atlas->tex_width = *width;
12226  atlas->tex_height = *height;
12227 
12228  /* initialize each font */
12229  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12230  struct nk_font *font = font_iter;
12231  struct nk_font_config *config = font->config;
12232  nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
12233  config->font, nk_handle_ptr(0));
12234  }
12235 
12236  /* initialize each cursor */
12237  {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
12238  /* Pos ----- Size ------- Offset --*/
12239  {{ 0, 3}, {12,19}, { 0, 0}},
12240  {{13, 0}, { 7,16}, { 4, 8}},
12241  {{31, 0}, {23,23}, {11,11}},
12242  {{21, 0}, { 9, 23}, { 5,11}},
12243  {{55,18}, {23, 9}, {11, 5}},
12244  {{73, 0}, {17,17}, { 9, 9}},
12245  {{55, 0}, {17,17}, { 9, 9}}
12246  };
12247  for (i = 0; i < NK_CURSOR_COUNT; ++i) {
12248  struct nk_cursor *cursor = &atlas->cursors[i];
12249  cursor->img.w = (unsigned short)*width;
12250  cursor->img.h = (unsigned short)*height;
12251  cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
12252  cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
12253  cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
12254  cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
12255  cursor->size = nk_cursor_data[i][1];
12256  cursor->offset = nk_cursor_data[i][2];
12257  }}
12258  /* free temporary memory */
12259  atlas->temporary.free(atlas->temporary.userdata, tmp);
12260  return atlas->pixel;
12261 
12262 failed:
12263  /* error so cleanup all memory */
12264  if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
12265  if (atlas->glyphs) {
12266  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12267  atlas->glyphs = 0;
12268  }
12269  if (atlas->pixel) {
12270  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12271  atlas->pixel = 0;
12272  }
12273  return 0;
12274 }
12275 
12276 NK_API void
12277 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
12278  struct nk_draw_null_texture *null)
12279 {
12280  int i = 0;
12281  struct nk_font *font_iter;
12282  NK_ASSERT(atlas);
12283  if (!atlas) {
12284  if (!null) return;
12285  null->texture = texture;
12286  null->uv = nk_vec2(0.5f,0.5f);
12287  }
12288  if (null) {
12289  null->texture = texture;
12290  null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
12291  null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
12292  }
12293  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12294  font_iter->texture = texture;
12295 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12296  font_iter->handle.texture = texture;
12297 #endif
12298  }
12299  for (i = 0; i < NK_CURSOR_COUNT; ++i)
12300  atlas->cursors[i].img.handle = texture;
12301 
12302  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12303  atlas->pixel = 0;
12304  atlas->tex_width = 0;
12305  atlas->tex_height = 0;
12306  atlas->custom.x = 0;
12307  atlas->custom.y = 0;
12308  atlas->custom.w = 0;
12309  atlas->custom.h = 0;
12310 }
12311 
12312 NK_API void
12313 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
12314 {
12315  NK_ASSERT(atlas);
12316  NK_ASSERT(atlas->temporary.alloc);
12317  NK_ASSERT(atlas->temporary.free);
12318  NK_ASSERT(atlas->permanent.alloc);
12319  NK_ASSERT(atlas->permanent.free);
12320 
12321  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12322  if (atlas->config) {
12323  struct nk_font_config *iter, *next;
12324  for (iter = atlas->config; iter; iter = next) {
12325  next = iter->next;
12326  atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
12327  atlas->permanent.free(atlas->permanent.userdata, iter);
12328  }
12329  }
12330 }
12331 
12332 NK_API void
12333 nk_font_atlas_clear(struct nk_font_atlas *atlas)
12334 {
12335  NK_ASSERT(atlas);
12336  NK_ASSERT(atlas->temporary.alloc);
12337  NK_ASSERT(atlas->temporary.free);
12338  NK_ASSERT(atlas->permanent.alloc);
12339  NK_ASSERT(atlas->permanent.free);
12340  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12341 
12342  nk_font_atlas_cleanup(atlas);
12343  if (atlas->fonts) {
12344  struct nk_font *iter, *next;
12345  for (iter = atlas->fonts; iter; iter = next) {
12346  next = iter->next;
12347  atlas->permanent.free(atlas->permanent.userdata, iter);
12348  }
12349  atlas->fonts = 0;
12350  }
12351  if (atlas->glyphs)
12352  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12353  nk_zero_struct(*atlas);
12354 }
12355 #endif
12356 /* ==============================================================
12357  *
12358  * INPUT
12359  *
12360  * ===============================================================*/
12361 NK_API void
12362 nk_input_begin(struct nk_context *ctx)
12363 {
12364  int i;
12365  struct nk_input *in;
12366  NK_ASSERT(ctx);
12367  if (!ctx) return;
12368  in = &ctx->input;
12369  for (i = 0; i < NK_BUTTON_MAX; ++i)
12370  in->mouse.buttons[i].clicked = 0;
12371 
12372  in->keyboard.text_len = 0;
12373  in->mouse.scroll_delta = nk_vec2(0,0);
12374  in->mouse.prev.x = in->mouse.pos.x;
12375  in->mouse.prev.y = in->mouse.pos.y;
12376  in->mouse.delta.x = 0;
12377  in->mouse.delta.y = 0;
12378  for (i = 0; i < NK_KEY_MAX; i++)
12379  in->keyboard.keys[i].clicked = 0;
12380 }
12381 
12382 NK_API void
12383 nk_input_end(struct nk_context *ctx)
12384 {
12385  struct nk_input *in;
12386  NK_ASSERT(ctx);
12387  if (!ctx) return;
12388  in = &ctx->input;
12389  if (in->mouse.grab)
12390  in->mouse.grab = 0;
12391  if (in->mouse.ungrab) {
12392  in->mouse.grabbed = 0;
12393  in->mouse.ungrab = 0;
12394  in->mouse.grab = 0;
12395  }
12396 }
12397 
12398 NK_API void
12399 nk_input_motion(struct nk_context *ctx, int x, int y)
12400 {
12401  struct nk_input *in;
12402  NK_ASSERT(ctx);
12403  if (!ctx) return;
12404  in = &ctx->input;
12405  in->mouse.pos.x = (float)x;
12406  in->mouse.pos.y = (float)y;
12407  in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
12408  in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
12409 }
12410 
12411 NK_API void
12412 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
12413 {
12414  struct nk_input *in;
12415  NK_ASSERT(ctx);
12416  if (!ctx) return;
12417  in = &ctx->input;
12418  if (in->keyboard.keys[key].down != down)
12419  in->keyboard.keys[key].clicked++;
12420  in->keyboard.keys[key].down = down;
12421 }
12422 
12423 NK_API void
12424 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
12425 {
12426  struct nk_mouse_button *btn;
12427  struct nk_input *in;
12428  NK_ASSERT(ctx);
12429  if (!ctx) return;
12430  in = &ctx->input;
12431  if (in->mouse.buttons[id].down == down) return;
12432 
12433  btn = &in->mouse.buttons[id];
12434  btn->clicked_pos.x = (float)x;
12435  btn->clicked_pos.y = (float)y;
12436  btn->down = down;
12437  btn->clicked++;
12438 }
12439 
12440 NK_API void
12441 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
12442 {
12443  NK_ASSERT(ctx);
12444  if (!ctx) return;
12445  ctx->input.mouse.scroll_delta.x += val.x;
12446  ctx->input.mouse.scroll_delta.y += val.y;
12447 }
12448 
12449 NK_API void
12450 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
12451 {
12452  int len = 0;
12453  nk_rune unicode;
12454  struct nk_input *in;
12455 
12456  NK_ASSERT(ctx);
12457  if (!ctx) return;
12458  in = &ctx->input;
12459 
12460  len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
12461  if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
12462  nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
12464  in->keyboard.text_len += len;
12465  }
12466 }
12467 
12468 NK_API void
12469 nk_input_char(struct nk_context *ctx, char c)
12470 {
12471  nk_glyph glyph;
12472  NK_ASSERT(ctx);
12473  if (!ctx) return;
12474  glyph[0] = c;
12475  nk_input_glyph(ctx, glyph);
12476 }
12477 
12478 NK_API void
12479 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
12480 {
12481  nk_glyph rune;
12482  NK_ASSERT(ctx);
12483  if (!ctx) return;
12484  nk_utf_encode(unicode, rune, NK_UTF_SIZE);
12485  nk_input_glyph(ctx, rune);
12486 }
12487 
12488 NK_API int
12489 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
12490 {
12491  const struct nk_mouse_button *btn;
12492  if (!i) return nk_false;
12493  btn = &i->mouse.buttons[id];
12494  return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
12495 }
12496 
12497 NK_API int
12498 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12499  struct nk_rect b)
12500 {
12501  const struct nk_mouse_button *btn;
12502  if (!i) return nk_false;
12503  btn = &i->mouse.buttons[id];
12504  if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
12505  return nk_false;
12506  return nk_true;
12507 }
12508 
12509 NK_API int
12511  struct nk_rect b, int down)
12512 {
12513  const struct nk_mouse_button *btn;
12514  if (!i) return nk_false;
12515  btn = &i->mouse.buttons[id];
12516  return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
12517 }
12518 
12519 NK_API int
12520 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12521  struct nk_rect b)
12522 {
12523  const struct nk_mouse_button *btn;
12524  if (!i) return nk_false;
12525  btn = &i->mouse.buttons[id];
12526  return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
12527  btn->clicked) ? nk_true : nk_false;
12528 }
12529 
12530 NK_API int
12532  struct nk_rect b, int down)
12533 {
12534  const struct nk_mouse_button *btn;
12535  if (!i) return nk_false;
12536  btn = &i->mouse.buttons[id];
12537  return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
12538  btn->clicked) ? nk_true : nk_false;
12539 }
12540 
12541 NK_API int
12542 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
12543 {
12544  int i, down = 0;
12545  for (i = 0; i < NK_BUTTON_MAX; ++i)
12546  down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
12547  return down;
12548 }
12549 
12550 NK_API int
12551 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12552 {
12553  if (!i) return nk_false;
12554  return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
12555 }
12556 
12557 NK_API int
12558 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12559 {
12560  if (!i) return nk_false;
12561  return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
12562 }
12563 
12564 NK_API int
12565 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
12566 {
12567  if (!i) return nk_false;
12568  if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
12569  return nk_input_is_mouse_click_in_rect(i, id, rect);
12570 }
12571 
12572 NK_API int
12573 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
12574 {
12575  if (!i) return nk_false;
12576  return i->mouse.buttons[id].down;
12577 }
12578 
12579 NK_API int
12580 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
12581 {
12582  const struct nk_mouse_button *b;
12583  if (!i) return nk_false;
12584  b = &i->mouse.buttons[id];
12585  if (b->down && b->clicked)
12586  return nk_true;
12587  return nk_false;
12588 }
12589 
12590 NK_API int
12591 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
12592 {
12593  if (!i) return nk_false;
12594  return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
12595 }
12596 
12597 NK_API int
12598 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
12599 {
12600  const struct nk_key *k;
12601  if (!i) return nk_false;
12602  k = &i->keyboard.keys[key];
12603  if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
12604  return nk_true;
12605  return nk_false;
12606 }
12607 
12608 NK_API int
12609 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
12610 {
12611  const struct nk_key *k;
12612  if (!i) return nk_false;
12613  k = &i->keyboard.keys[key];
12614  if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
12615  return nk_true;
12616  return nk_false;
12617 }
12618 
12619 NK_API int
12620 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
12621 {
12622  const struct nk_key *k;
12623  if (!i) return nk_false;
12624  k = &i->keyboard.keys[key];
12625  if (k->down) return nk_true;
12626  return nk_false;
12627 }
12628 
12629 /*
12630  * ==============================================================
12631  *
12632  * TEXT EDITOR
12633  *
12634  * ===============================================================
12635  */
12636 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */
12637 struct nk_text_find {
12638  float x,y; /* position of n'th character */
12639  float height; /* height of line */
12640  int first_char, length; /* first char of row, and length */
12641  int prev_first; /*_ first char of previous row */
12642 };
12643 
12644 struct nk_text_edit_row {
12645  float x0,x1;
12646  /* starting x location, end x location (allows for align=right, etc) */
12647  float baseline_y_delta;
12648  /* position of baseline relative to previous row's baseline*/
12649  float ymin,ymax;
12650  /* height of row above and below baseline */
12651  int num_chars;
12652 };
12653 
12654 /* forward declarations */
12655 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
12656 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
12657 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
12658 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
12659 
12660 NK_INTERN float
12661 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
12662  const struct nk_user_font *font)
12663 {
12664  int len = 0;
12665  nk_rune unicode = 0;
12666  const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
12667  return font->width(font->userdata, font->height, str, len);
12668 }
12669 
12670 NK_INTERN void
12671 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
12672  int line_start_id, float row_height, const struct nk_user_font *font)
12673 {
12674  int l;
12675  int glyphs = 0;
12676  nk_rune unicode;
12677  const char *remaining;
12678  int len = nk_str_len_char(&edit->string);
12679  const char *end = nk_str_get_const(&edit->string) + len;
12680  const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
12681  const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
12682  text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
12683 
12684  r->x0 = 0.0f;
12685  r->x1 = size.x;
12686  r->baseline_y_delta = size.y;
12687  r->ymin = 0.0f;
12688  r->ymax = size.y;
12689  r->num_chars = glyphs;
12690 }
12691 
12692 NK_INTERN int
12693 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
12694  const struct nk_user_font *font, float row_height)
12695 {
12696  struct nk_text_edit_row r;
12697  int n = edit->string.len;
12698  float base_y = 0, prev_x;
12699  int i=0, k;
12700 
12701  r.x0 = r.x1 = 0;
12702  r.ymin = r.ymax = 0;
12703  r.num_chars = 0;
12704 
12705  /* search rows to find one that straddles 'y' */
12706  while (i < n) {
12707  nk_textedit_layout_row(&r, edit, i, row_height, font);
12708  if (r.num_chars <= 0)
12709  return n;
12710 
12711  if (i==0 && y < base_y + r.ymin)
12712  return 0;
12713 
12714  if (y < base_y + r.ymax)
12715  break;
12716 
12717  i += r.num_chars;
12718  base_y += r.baseline_y_delta;
12719  }
12720 
12721  /* below all text, return 'after' last character */
12722  if (i >= n)
12723  return n;
12724 
12725  /* check if it's before the beginning of the line */
12726  if (x < r.x0)
12727  return i;
12728 
12729  /* check if it's before the end of the line */
12730  if (x < r.x1) {
12731  /* search characters in row for one that straddles 'x' */
12732  k = i;
12733  prev_x = r.x0;
12734  for (i=0; i < r.num_chars; ++i) {
12735  float w = nk_textedit_get_width(edit, k, i, font);
12736  if (x < prev_x+w) {
12737  if (x < prev_x+w/2)
12738  return k+i;
12739  else return k+i+1;
12740  }
12741  prev_x += w;
12742  }
12743  /* shouldn't happen, but if it does, fall through to end-of-line case */
12744  }
12745 
12746  /* if the last character is a newline, return that.
12747  * otherwise return 'after' the last character */
12748  if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
12749  return i+r.num_chars-1;
12750  else return i+r.num_chars;
12751 }
12752 
12753 NK_INTERN void
12754 nk_textedit_click(struct nk_text_edit *state, float x, float y,
12755  const struct nk_user_font *font, float row_height)
12756 {
12757  /* API click: on mouse down, move the cursor to the clicked location,
12758  * and reset the selection */
12759  state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
12760  state->select_start = state->cursor;
12761  state->select_end = state->cursor;
12762  state->has_preferred_x = 0;
12763 }
12764 
12765 NK_INTERN void
12766 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
12767  const struct nk_user_font *font, float row_height)
12768 {
12769  /* API drag: on mouse drag, move the cursor and selection endpoint
12770  * to the clicked location */
12771  int p = nk_textedit_locate_coord(state, x, y, font, row_height);
12772  if (state->select_start == state->select_end)
12773  state->select_start = state->cursor;
12774  state->cursor = state->select_end = p;
12775 }
12776 
12777 NK_INTERN void
12778 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
12779  int n, int single_line, const struct nk_user_font *font, float row_height)
12780 {
12781  /* find the x/y location of a character, and remember info about the previous
12782  * row in case we get a move-up event (for page up, we'll have to rescan) */
12783  struct nk_text_edit_row r;
12784  int prev_start = 0;
12785  int z = state->string.len;
12786  int i=0, first;
12787 
12788  nk_zero_struct(r);
12789  if (n == z) {
12790  /* if it's at the end, then find the last line -- simpler than trying to
12791  explicitly handle this case in the regular code */
12792  nk_textedit_layout_row(&r, state, 0, row_height, font);
12793  if (single_line) {
12794  find->first_char = 0;
12795  find->length = z;
12796  } else {
12797  while (i < z) {
12798  prev_start = i;
12799  i += r.num_chars;
12800  nk_textedit_layout_row(&r, state, i, row_height, font);
12801  }
12802 
12803  find->first_char = i;
12804  find->length = r.num_chars;
12805  }
12806  find->x = r.x1;
12807  find->y = r.ymin;
12808  find->height = r.ymax - r.ymin;
12809  find->prev_first = prev_start;
12810  return;
12811  }
12812 
12813  /* search rows to find the one that straddles character n */
12814  find->y = 0;
12815 
12816  for(;;) {
12817  nk_textedit_layout_row(&r, state, i, row_height, font);
12818  if (n < i + r.num_chars) break;
12819  prev_start = i;
12820  i += r.num_chars;
12821  find->y += r.baseline_y_delta;
12822  }
12823 
12824  find->first_char = first = i;
12825  find->length = r.num_chars;
12826  find->height = r.ymax - r.ymin;
12827  find->prev_first = prev_start;
12828 
12829  /* now scan to find xpos */
12830  find->x = r.x0;
12831  for (i=0; first+i < n; ++i)
12832  find->x += nk_textedit_get_width(state, first, i, font);
12833 }
12834 
12835 NK_INTERN void
12836 nk_textedit_clamp(struct nk_text_edit *state)
12837 {
12838  /* make the selection/cursor state valid if client altered the string */
12839  int n = state->string.len;
12840  if (NK_TEXT_HAS_SELECTION(state)) {
12841  if (state->select_start > n) state->select_start = n;
12842  if (state->select_end > n) state->select_end = n;
12843  /* if clamping forced them to be equal, move the cursor to match */
12844  if (state->select_start == state->select_end)
12845  state->cursor = state->select_start;
12846  }
12847  if (state->cursor > n) state->cursor = n;
12848 }
12849 
12850 NK_API void
12851 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
12852 {
12853  /* delete characters while updating undo */
12854  nk_textedit_makeundo_delete(state, where, len);
12855  nk_str_delete_runes(&state->string, where, len);
12856  state->has_preferred_x = 0;
12857 }
12858 
12859 NK_API void
12861 {
12862  /* delete the section */
12863  nk_textedit_clamp(state);
12864  if (NK_TEXT_HAS_SELECTION(state)) {
12865  if (state->select_start < state->select_end) {
12866  nk_textedit_delete(state, state->select_start,
12867  state->select_end - state->select_start);
12868  state->select_end = state->cursor = state->select_start;
12869  } else {
12870  nk_textedit_delete(state, state->select_end,
12871  state->select_start - state->select_end);
12872  state->select_start = state->cursor = state->select_end;
12873  }
12874  state->has_preferred_x = 0;
12875  }
12876 }
12877 
12878 NK_INTERN void
12879 nk_textedit_sortselection(struct nk_text_edit *state)
12880 {
12881  /* canonicalize the selection so start <= end */
12882  if (state->select_end < state->select_start) {
12883  int temp = state->select_end;
12884  state->select_end = state->select_start;
12885  state->select_start = temp;
12886  }
12887 }
12888 
12889 NK_INTERN void
12890 nk_textedit_move_to_first(struct nk_text_edit *state)
12891 {
12892  /* move cursor to first character of selection */
12893  if (NK_TEXT_HAS_SELECTION(state)) {
12894  nk_textedit_sortselection(state);
12895  state->cursor = state->select_start;
12896  state->select_end = state->select_start;
12897  state->has_preferred_x = 0;
12898  }
12899 }
12900 
12901 NK_INTERN void
12902 nk_textedit_move_to_last(struct nk_text_edit *state)
12903 {
12904  /* move cursor to last character of selection */
12905  if (NK_TEXT_HAS_SELECTION(state)) {
12906  nk_textedit_sortselection(state);
12907  nk_textedit_clamp(state);
12908  state->cursor = state->select_end;
12909  state->select_start = state->select_end;
12910  state->has_preferred_x = 0;
12911  }
12912 }
12913 
12914 NK_INTERN int
12915 nk_is_word_boundary( struct nk_text_edit *state, int idx)
12916 {
12917  int len;
12918  nk_rune c;
12919  if (idx <= 0) return 1;
12920  if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
12921  return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
12922  c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
12923  c == '|');
12924 }
12925 
12926 NK_INTERN int
12927 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
12928 {
12929  int c = state->cursor - 1;
12930  while( c >= 0 && !nk_is_word_boundary(state, c))
12931  --c;
12932 
12933  if( c < 0 )
12934  c = 0;
12935 
12936  return c;
12937 }
12938 
12939 NK_INTERN int
12940 nk_textedit_move_to_word_next(struct nk_text_edit *state)
12941 {
12942  const int len = state->string.len;
12943  int c = state->cursor+1;
12944  while( c < len && !nk_is_word_boundary(state, c))
12945  ++c;
12946 
12947  if( c > len )
12948  c = len;
12949 
12950  return c;
12951 }
12952 
12953 NK_INTERN void
12954 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
12955 {
12956  /* update selection and cursor to match each other */
12957  if (!NK_TEXT_HAS_SELECTION(state))
12958  state->select_start = state->select_end = state->cursor;
12959  else state->cursor = state->select_end;
12960 }
12961 
12962 NK_API int
12963 nk_textedit_cut(struct nk_text_edit *state)
12964 {
12965  /* API cut: delete selection */
12966  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
12967  return 0;
12968  if (NK_TEXT_HAS_SELECTION(state)) {
12969  nk_textedit_delete_selection(state); /* implicitly clamps */
12970  state->has_preferred_x = 0;
12971  return 1;
12972  }
12973  return 0;
12974 }
12975 
12976 NK_API int
12977 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
12978 {
12979  /* API paste: replace existing selection with passed-in text */
12980  int glyphs;
12981  const char *text = (const char *) ctext;
12982  if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
12983 
12984  /* if there's a selection, the paste should delete it */
12985  nk_textedit_clamp(state);
12987 
12988  /* try to insert the characters */
12989  glyphs = nk_utf_len(ctext, len);
12990  if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
12991  nk_textedit_makeundo_insert(state, state->cursor, glyphs);
12992  state->cursor += len;
12993  state->has_preferred_x = 0;
12994  return 1;
12995  }
12996  /* remove the undo since we didn't actually insert the characters */
12997  if (state->undo.undo_point)
12998  --state->undo.undo_point;
12999  return 0;
13000 }
13001 
13002 NK_API void
13003 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
13004 {
13005  nk_rune unicode;
13006  int glyph_len;
13007  int text_len = 0;
13008 
13009  NK_ASSERT(state);
13010  NK_ASSERT(text);
13011  if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
13012 
13013  glyph_len = nk_utf_decode(text, &unicode, total_len);
13014  while ((text_len < total_len) && glyph_len)
13015  {
13016  /* don't insert a backward delete, just process the event */
13017  if (unicode == 127) goto next;
13018  /* can't add newline in single-line mode */
13019  if (unicode == '\n' && state->single_line) goto next;
13020  /* filter incoming text */
13021  if (state->filter && !state->filter(state, unicode)) goto next;
13022 
13023  if (!NK_TEXT_HAS_SELECTION(state) &&
13024  state->cursor < state->string.len)
13025  {
13026  if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
13027  nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
13028  nk_str_delete_runes(&state->string, state->cursor, 1);
13029  }
13030  if (nk_str_insert_text_utf8(&state->string, state->cursor,
13031  text+text_len, 1))
13032  {
13033  ++state->cursor;
13034  state->has_preferred_x = 0;
13035  }
13036  } else {
13037  nk_textedit_delete_selection(state); /* implicitly clamps */
13038  if (nk_str_insert_text_utf8(&state->string, state->cursor,
13039  text+text_len, 1))
13040  {
13041  nk_textedit_makeundo_insert(state, state->cursor, 1);
13042  ++state->cursor;
13043  state->has_preferred_x = 0;
13044  }
13045  }
13046  next:
13047  text_len += glyph_len;
13048  glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
13049  }
13050 }
13051 
13052 NK_INTERN void
13053 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
13054  const struct nk_user_font *font, float row_height)
13055 {
13056 retry:
13057  switch (key)
13058  {
13059  case NK_KEY_NONE:
13060  case NK_KEY_CTRL:
13061  case NK_KEY_ENTER:
13062  case NK_KEY_SHIFT:
13063  case NK_KEY_TAB:
13064  case NK_KEY_COPY:
13065  case NK_KEY_CUT:
13066  case NK_KEY_PASTE:
13067  case NK_KEY_MAX:
13068  default: break;
13069  case NK_KEY_TEXT_UNDO:
13070  nk_textedit_undo(state);
13071  state->has_preferred_x = 0;
13072  break;
13073 
13074  case NK_KEY_TEXT_REDO:
13075  nk_textedit_redo(state);
13076  state->has_preferred_x = 0;
13077  break;
13078 
13080  nk_textedit_select_all(state);
13081  state->has_preferred_x = 0;
13082  break;
13083 
13085  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13086  state->mode = NK_TEXT_EDIT_MODE_INSERT;
13087  break;
13089  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13091  break;
13093  if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
13094  state->mode == NK_TEXT_EDIT_MODE_REPLACE)
13095  state->mode = NK_TEXT_EDIT_MODE_VIEW;
13096  break;
13097 
13098  case NK_KEY_LEFT:
13099  if (shift_mod) {
13100  nk_textedit_clamp(state);
13101  nk_textedit_prep_selection_at_cursor(state);
13102  /* move selection left */
13103  if (state->select_end > 0)
13104  --state->select_end;
13105  state->cursor = state->select_end;
13106  state->has_preferred_x = 0;
13107  } else {
13108  /* if currently there's a selection,
13109  * move cursor to start of selection */
13110  if (NK_TEXT_HAS_SELECTION(state))
13111  nk_textedit_move_to_first(state);
13112  else if (state->cursor > 0)
13113  --state->cursor;
13114  state->has_preferred_x = 0;
13115  } break;
13116 
13117  case NK_KEY_RIGHT:
13118  if (shift_mod) {
13119  nk_textedit_prep_selection_at_cursor(state);
13120  /* move selection right */
13121  ++state->select_end;
13122  nk_textedit_clamp(state);
13123  state->cursor = state->select_end;
13124  state->has_preferred_x = 0;
13125  } else {
13126  /* if currently there's a selection,
13127  * move cursor to end of selection */
13128  if (NK_TEXT_HAS_SELECTION(state))
13129  nk_textedit_move_to_last(state);
13130  else ++state->cursor;
13131  nk_textedit_clamp(state);
13132  state->has_preferred_x = 0;
13133  } break;
13134 
13135  case NK_KEY_TEXT_WORD_LEFT:
13136  if (shift_mod) {
13137  if( !NK_TEXT_HAS_SELECTION( state ) )
13138  nk_textedit_prep_selection_at_cursor(state);
13139  state->cursor = nk_textedit_move_to_word_previous(state);
13140  state->select_end = state->cursor;
13141  nk_textedit_clamp(state );
13142  } else {
13143  if (NK_TEXT_HAS_SELECTION(state))
13144  nk_textedit_move_to_first(state);
13145  else {
13146  state->cursor = nk_textedit_move_to_word_previous(state);
13147  nk_textedit_clamp(state );
13148  }
13149  } break;
13150 
13152  if (shift_mod) {
13153  if( !NK_TEXT_HAS_SELECTION( state ) )
13154  nk_textedit_prep_selection_at_cursor(state);
13155  state->cursor = nk_textedit_move_to_word_next(state);
13156  state->select_end = state->cursor;
13157  nk_textedit_clamp(state);
13158  } else {
13159  if (NK_TEXT_HAS_SELECTION(state))
13160  nk_textedit_move_to_last(state);
13161  else {
13162  state->cursor = nk_textedit_move_to_word_next(state);
13163  nk_textedit_clamp(state );
13164  }
13165  } break;
13166 
13167  case NK_KEY_DOWN: {
13168  struct nk_text_find find;
13169  struct nk_text_edit_row row;
13170  int i, sel = shift_mod;
13171 
13172  if (state->single_line) {
13173  /* on windows, up&down in single-line behave like left&right */
13174  key = NK_KEY_RIGHT;
13175  goto retry;
13176  }
13177 
13178  if (sel)
13179  nk_textedit_prep_selection_at_cursor(state);
13180  else if (NK_TEXT_HAS_SELECTION(state))
13181  nk_textedit_move_to_last(state);
13182 
13183  /* compute current position of cursor point */
13184  nk_textedit_clamp(state);
13185  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13186  font, row_height);
13187 
13188  /* now find character position down a row */
13189  if (find.length)
13190  {
13191  float x;
13192  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13193  int start = find.first_char + find.length;
13194 
13195  state->cursor = start;
13196  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13197  x = row.x0;
13198 
13199  for (i=0; i < row.num_chars && x < row.x1; ++i) {
13200  float dx = nk_textedit_get_width(state, start, i, font);
13201  x += dx;
13202  if (x > goal_x)
13203  break;
13204  ++state->cursor;
13205  }
13206  nk_textedit_clamp(state);
13207 
13208  state->has_preferred_x = 1;
13209  state->preferred_x = goal_x;
13210  if (sel)
13211  state->select_end = state->cursor;
13212  }
13213  } break;
13214 
13215  case NK_KEY_UP: {
13216  struct nk_text_find find;
13217  struct nk_text_edit_row row;
13218  int i, sel = shift_mod;
13219 
13220  if (state->single_line) {
13221  /* on windows, up&down become left&right */
13222  key = NK_KEY_LEFT;
13223  goto retry;
13224  }
13225 
13226  if (sel)
13227  nk_textedit_prep_selection_at_cursor(state);
13228  else if (NK_TEXT_HAS_SELECTION(state))
13229  nk_textedit_move_to_first(state);
13230 
13231  /* compute current position of cursor point */
13232  nk_textedit_clamp(state);
13233  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13234  font, row_height);
13235 
13236  /* can only go up if there's a previous row */
13237  if (find.prev_first != find.first_char) {
13238  /* now find character position up a row */
13239  float x;
13240  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13241 
13242  state->cursor = find.prev_first;
13243  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13244  x = row.x0;
13245 
13246  for (i=0; i < row.num_chars && x < row.x1; ++i) {
13247  float dx = nk_textedit_get_width(state, find.prev_first, i, font);
13248  x += dx;
13249  if (x > goal_x)
13250  break;
13251  ++state->cursor;
13252  }
13253  nk_textedit_clamp(state);
13254 
13255  state->has_preferred_x = 1;
13256  state->preferred_x = goal_x;
13257  if (sel) state->select_end = state->cursor;
13258  }
13259  } break;
13260 
13261  case NK_KEY_DEL:
13262  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13263  break;
13264  if (NK_TEXT_HAS_SELECTION(state))
13266  else {
13267  int n = state->string.len;
13268  if (state->cursor < n)
13269  nk_textedit_delete(state, state->cursor, 1);
13270  }
13271  state->has_preferred_x = 0;
13272  break;
13273 
13274  case NK_KEY_BACKSPACE:
13275  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13276  break;
13277  if (NK_TEXT_HAS_SELECTION(state))
13279  else {
13280  nk_textedit_clamp(state);
13281  if (state->cursor > 0) {
13282  nk_textedit_delete(state, state->cursor-1, 1);
13283  --state->cursor;
13284  }
13285  }
13286  state->has_preferred_x = 0;
13287  break;
13288 
13289  case NK_KEY_TEXT_START:
13290  if (shift_mod) {
13291  nk_textedit_prep_selection_at_cursor(state);
13292  state->cursor = state->select_end = 0;
13293  state->has_preferred_x = 0;
13294  } else {
13295  state->cursor = state->select_start = state->select_end = 0;
13296  state->has_preferred_x = 0;
13297  }
13298  break;
13299 
13300  case NK_KEY_TEXT_END:
13301  if (shift_mod) {
13302  nk_textedit_prep_selection_at_cursor(state);
13303  state->cursor = state->select_end = state->string.len;
13304  state->has_preferred_x = 0;
13305  } else {
13306  state->cursor = state->string.len;
13307  state->select_start = state->select_end = 0;
13308  state->has_preferred_x = 0;
13309  }
13310  break;
13311 
13312  case NK_KEY_TEXT_LINE_START: {
13313  if (shift_mod) {
13314  struct nk_text_find find;
13315  nk_textedit_clamp(state);
13316  nk_textedit_prep_selection_at_cursor(state);
13317  if (state->string.len && state->cursor == state->string.len)
13318  --state->cursor;
13319  nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
13320  font, row_height);
13321  state->cursor = state->select_end = find.first_char;
13322  state->has_preferred_x = 0;
13323  } else {
13324  struct nk_text_find find;
13325  if (state->string.len && state->cursor == state->string.len)
13326  --state->cursor;
13327  nk_textedit_clamp(state);
13328  nk_textedit_move_to_first(state);
13329  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13330  font, row_height);
13331  state->cursor = find.first_char;
13332  state->has_preferred_x = 0;
13333  }
13334  } break;
13335 
13336  case NK_KEY_TEXT_LINE_END: {
13337  if (shift_mod) {
13338  struct nk_text_find find;
13339  nk_textedit_clamp(state);
13340  nk_textedit_prep_selection_at_cursor(state);
13341  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13342  font, row_height);
13343  state->has_preferred_x = 0;
13344  state->cursor = find.first_char + find.length;
13345  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13346  --state->cursor;
13347  state->select_end = state->cursor;
13348  } else {
13349  struct nk_text_find find;
13350  nk_textedit_clamp(state);
13351  nk_textedit_move_to_first(state);
13352  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13353  font, row_height);
13354 
13355  state->has_preferred_x = 0;
13356  state->cursor = find.first_char + find.length;
13357  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13358  --state->cursor;
13359  }} break;
13360  }
13361 }
13362 
13363 NK_INTERN void
13364 nk_textedit_flush_redo(struct nk_text_undo_state *state)
13365 {
13368 }
13369 
13370 NK_INTERN void
13371 nk_textedit_discard_undo(struct nk_text_undo_state *state)
13372 {
13373  /* discard the oldest entry in the undo list */
13374  if (state->undo_point > 0) {
13375  /* if the 0th undo state has characters, clean those up */
13376  if (state->undo_rec[0].char_storage >= 0) {
13377  int n = state->undo_rec[0].insert_length, i;
13378  /* delete n characters from all other records */
13379  state->undo_char_point = (short)(state->undo_char_point - n);
13380  NK_MEMCPY(state->undo_char, state->undo_char + n,
13381  (nk_size)state->undo_char_point*sizeof(nk_rune));
13382  for (i=0; i < state->undo_point; ++i) {
13383  if (state->undo_rec[i].char_storage >= 0)
13384  state->undo_rec[i].char_storage = (short)
13385  (state->undo_rec[i].char_storage - n);
13386  }
13387  }
13388  --state->undo_point;
13389  NK_MEMCPY(state->undo_rec, state->undo_rec+1,
13390  (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
13391  }
13392 }
13393 
13394 NK_INTERN void
13395 nk_textedit_discard_redo(struct nk_text_undo_state *state)
13396 {
13397 /* discard the oldest entry in the redo list--it's bad if this
13398  ever happens, but because undo & redo have to store the actual
13399  characters in different cases, the redo character buffer can
13400  fill up even though the undo buffer didn't */
13401  nk_size num;
13402  int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
13403  if (state->redo_point <= k) {
13404  /* if the k'th undo state has characters, clean those up */
13405  if (state->undo_rec[k].char_storage >= 0) {
13406  int n = state->undo_rec[k].insert_length, i;
13407  /* delete n characters from all other records */
13408  state->redo_char_point = (short)(state->redo_char_point + n);
13410  NK_MEMCPY(state->undo_char + state->redo_char_point,
13411  state->undo_char + state->redo_char_point-n, num * sizeof(char));
13412  for (i = state->redo_point; i < k; ++i) {
13413  if (state->undo_rec[i].char_storage >= 0) {
13414  state->undo_rec[i].char_storage = (short)
13415  (state->undo_rec[i].char_storage + n);
13416  }
13417  }
13418  }
13419  ++state->redo_point;
13420  num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
13421  if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
13422  state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
13423  }
13424 }
13425 
13427 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
13428 {
13429  /* any time we create a new undo record, we discard redo*/
13430  nk_textedit_flush_redo(state);
13431 
13432  /* if we have no free records, we have to make room,
13433  * by sliding the existing records down */
13434  if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13435  nk_textedit_discard_undo(state);
13436 
13437  /* if the characters to store won't possibly fit in the buffer,
13438  * we can't undo */
13439  if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
13440  state->undo_point = 0;
13441  state->undo_char_point = 0;
13442  return 0;
13443  }
13444 
13445  /* if we don't have enough free characters in the buffer,
13446  * we have to make room */
13447  while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
13448  nk_textedit_discard_undo(state);
13449  return &state->undo_rec[state->undo_point++];
13450 }
13451 
13452 NK_INTERN nk_rune*
13453 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
13454  int insert_len, int delete_len)
13455 {
13456  struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
13457  if (r == 0)
13458  return 0;
13459 
13460  r->where = pos;
13461  r->insert_length = (short) insert_len;
13462  r->delete_length = (short) delete_len;
13463 
13464  if (insert_len == 0) {
13465  r->char_storage = -1;
13466  return 0;
13467  } else {
13468  r->char_storage = state->undo_char_point;
13469  state->undo_char_point = (short)(state->undo_char_point + insert_len);
13470  return &state->undo_char[r->char_storage];
13471  }
13472 }
13473 
13474 NK_API void
13475 nk_textedit_undo(struct nk_text_edit *state)
13476 {
13477  struct nk_text_undo_state *s = &state->undo;
13478  struct nk_text_undo_record u, *r;
13479  if (s->undo_point == 0)
13480  return;
13481 
13482  /* we need to do two things: apply the undo record, and create a redo record */
13483  u = s->undo_rec[s->undo_point-1];
13484  r = &s->undo_rec[s->redo_point-1];
13485  r->char_storage = -1;
13486 
13487  r->insert_length = u.delete_length;
13488  r->delete_length = u.insert_length;
13489  r->where = u.where;
13490 
13491  if (u.delete_length)
13492  {
13493  /* if the undo record says to delete characters, then the redo record will
13494  need to re-insert the characters that get deleted, so we need to store
13495  them.
13496  there are three cases:
13497  - there's enough room to store the characters
13498  - characters stored for *redoing* don't leave room for redo
13499  - characters stored for *undoing* don't leave room for redo
13500  if the last is true, we have to bail */
13501  if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
13502  /* the undo records take up too much character space; there's no space
13503  * to store the redo characters */
13504  r->insert_length = 0;
13505  } else {
13506  int i;
13507  /* there's definitely room to store the characters eventually */
13508  while (s->undo_char_point + u.delete_length > s->redo_char_point) {
13509  /* there's currently not enough room, so discard a redo record */
13510  nk_textedit_discard_redo(s);
13511  /* should never happen: */
13513  return;
13514  }
13515 
13516  r = &s->undo_rec[s->redo_point-1];
13517  r->char_storage = (short)(s->redo_char_point - u.delete_length);
13518  s->redo_char_point = (short)(s->redo_char_point - u.delete_length);
13519 
13520  /* now save the characters */
13521  for (i=0; i < u.delete_length; ++i)
13522  s->undo_char[r->char_storage + i] =
13523  nk_str_rune_at(&state->string, u.where + i);
13524  }
13525  /* now we can carry out the deletion */
13526  nk_str_delete_runes(&state->string, u.where, u.delete_length);
13527  }
13528 
13529  /* check type of recorded action: */
13530  if (u.insert_length) {
13531  /* easy case: was a deletion, so we need to insert n characters */
13532  nk_str_insert_text_runes(&state->string, u.where,
13533  &s->undo_char[u.char_storage], u.insert_length);
13534  s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
13535  }
13536  state->cursor = (short)(u.where + u.insert_length);
13537 
13538  s->undo_point--;
13539  s->redo_point--;
13540 }
13541 
13542 NK_API void
13543 nk_textedit_redo(struct nk_text_edit *state)
13544 {
13545  struct nk_text_undo_state *s = &state->undo;
13546  struct nk_text_undo_record *u, r;
13548  return;
13549 
13550  /* we need to do two things: apply the redo record, and create an undo record */
13551  u = &s->undo_rec[s->undo_point];
13552  r = s->undo_rec[s->redo_point];
13553 
13554  /* we KNOW there must be room for the undo record, because the redo record
13555  was derived from an undo record */
13558  u->where = r.where;
13559  u->char_storage = -1;
13560 
13561  if (r.delete_length) {
13562  /* the redo record requires us to delete characters, so the undo record
13563  needs to store the characters */
13564  if (s->undo_char_point + u->insert_length > s->redo_char_point) {
13565  u->insert_length = 0;
13566  u->delete_length = 0;
13567  } else {
13568  int i;
13569  u->char_storage = s->undo_char_point;
13570  s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
13571 
13572  /* now save the characters */
13573  for (i=0; i < u->insert_length; ++i) {
13574  s->undo_char[u->char_storage + i] =
13575  nk_str_rune_at(&state->string, u->where + i);
13576  }
13577  }
13579  }
13580 
13581  if (r.insert_length) {
13582  /* easy case: need to insert n characters */
13585  }
13586  state->cursor = r.where + r.insert_length;
13587 
13588  s->undo_point++;
13589  s->redo_point++;
13590 }
13591 
13592 NK_INTERN void
13593 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
13594 {
13595  nk_textedit_createundo(&state->undo, where, 0, length);
13596 }
13597 
13598 NK_INTERN void
13599 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
13600 {
13601  int i;
13602  nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
13603  if (p) {
13604  for (i=0; i < length; ++i)
13605  p[i] = nk_str_rune_at(&state->string, where+i);
13606  }
13607 }
13608 
13609 NK_INTERN void
13610 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
13611  int old_length, int new_length)
13612 {
13613  int i;
13614  nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
13615  if (p) {
13616  for (i=0; i < old_length; ++i)
13617  p[i] = nk_str_rune_at(&state->string, where+i);
13618  }
13619 }
13620 
13621 NK_INTERN void
13622 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
13623  nk_plugin_filter filter)
13624 {
13625  /* reset the state to default */
13626  state->undo.undo_point = 0;
13627  state->undo.undo_char_point = 0;
13630  state->select_end = state->select_start = 0;
13631  state->cursor = 0;
13632  state->has_preferred_x = 0;
13633  state->preferred_x = 0;
13634  state->cursor_at_end_of_line = 0;
13635  state->initialized = 1;
13636  state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
13637  state->mode = NK_TEXT_EDIT_MODE_VIEW;
13638  state->filter = filter;
13639  state->scrollbar = nk_vec2(0,0);
13640 }
13641 
13642 NK_API void
13643 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
13644 {
13645  NK_ASSERT(state);
13646  NK_ASSERT(memory);
13647  if (!state || !memory || !size) return;
13648  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13649  nk_str_init_fixed(&state->string, memory, size);
13650 }
13651 
13652 NK_API void
13653 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
13654 {
13655  NK_ASSERT(state);
13656  NK_ASSERT(alloc);
13657  if (!state || !alloc) return;
13658  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13659  nk_str_init(&state->string, alloc, size);
13660 }
13661 
13662 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13663 NK_API void
13664 nk_textedit_init_default(struct nk_text_edit *state)
13665 {
13666  NK_ASSERT(state);
13667  if (!state) return;
13668  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13669  nk_str_init_default(&state->string);
13670 }
13671 #endif
13672 
13673 NK_API void
13674 nk_textedit_select_all(struct nk_text_edit *state)
13675 {
13676  NK_ASSERT(state);
13677  state->select_start = 0;
13678  state->select_end = state->string.len;
13679 }
13680 
13681 NK_API void
13682 nk_textedit_free(struct nk_text_edit *state)
13683 {
13684  NK_ASSERT(state);
13685  if (!state) return;
13686  nk_str_free(&state->string);
13687 }
13688 
13689 /* ===============================================================
13690  *
13691  * TEXT WIDGET
13692  *
13693  * ===============================================================*/
13694 #define nk_widget_state_reset(s)\
13695  if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
13696  (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
13697  else (*(s)) = NK_WIDGET_STATE_INACTIVE;
13698 
13699 struct nk_text {
13700  struct nk_vec2 padding;
13701  struct nk_color background;
13702  struct nk_color text;
13703 };
13704 
13705 NK_INTERN void
13706 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
13707  const char *string, int len, const struct nk_text *t,
13708  nk_flags a, const struct nk_user_font *f)
13709 {
13710  struct nk_rect label;
13711  float text_width;
13712 
13713  NK_ASSERT(o);
13714  NK_ASSERT(t);
13715  if (!o || !t) return;
13716 
13717  b.h = NK_MAX(b.h, 2 * t->padding.y);
13718  label.x = 0; label.w = 0;
13719  label.y = b.y + t->padding.y;
13720  label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
13721 
13722  text_width = f->width(f->userdata, f->height, (const char*)string, len);
13723  text_width += (2.0f * t->padding.x);
13724 
13725  /* align in x-axis */
13726  if (a & NK_TEXT_ALIGN_LEFT) {
13727  label.x = b.x + t->padding.x;
13728  label.w = NK_MAX(0, b.w - 2 * t->padding.x);
13729  } else if (a & NK_TEXT_ALIGN_CENTERED) {
13730  label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
13731  label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
13732  label.x = NK_MAX(b.x + t->padding.x, label.x);
13733  label.w = NK_MIN(b.x + b.w, label.x + label.w);
13734  if (label.w >= label.x) label.w -= label.x;
13735  } else if (a & NK_TEXT_ALIGN_RIGHT) {
13736  label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
13737  label.w = (float)text_width + 2 * t->padding.x;
13738  } else return;
13739 
13740  /* align in y-axis */
13741  if (a & NK_TEXT_ALIGN_MIDDLE) {
13742  label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
13743  label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
13744  } else if (a & NK_TEXT_ALIGN_BOTTOM) {
13745  label.y = b.y + b.h - f->height;
13746  label.h = f->height;
13747  }
13748  nk_draw_text(o, label, (const char*)string,
13749  len, f, t->background, t->text);
13750 }
13751 
13752 NK_INTERN void
13753 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
13754  const char *string, int len, const struct nk_text *t,
13755  const struct nk_user_font *f)
13756 {
13757  float width;
13758  int glyphs = 0;
13759  int fitting = 0;
13760  int done = 0;
13761  struct nk_rect line;
13762  struct nk_text text;
13763  NK_INTERN nk_rune seperator[] = {' '};
13764 
13765  NK_ASSERT(o);
13766  NK_ASSERT(t);
13767  if (!o || !t) return;
13768 
13769  text.padding = nk_vec2(0,0);
13770  text.background = t->background;
13771  text.text = t->text;
13772 
13773  b.w = NK_MAX(b.w, 2 * t->padding.x);
13774  b.h = NK_MAX(b.h, 2 * t->padding.y);
13775  b.h = b.h - 2 * t->padding.y;
13776 
13777  line.x = b.x + t->padding.x;
13778  line.y = b.y + t->padding.y;
13779  line.w = b.w - 2 * t->padding.x;
13780  line.h = 2 * t->padding.y + f->height;
13781 
13782  fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
13783  while (done < len) {
13784  if (!fitting || line.y + line.h >= (b.y + b.h)) break;
13785  nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
13786  done += fitting;
13787  line.y += f->height + 2 * t->padding.y;
13788  fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
13789  }
13790 }
13791 
13792 /* ===============================================================
13793  *
13794  * BUTTON
13795  *
13796  * ===============================================================*/
13797 NK_INTERN void
13798 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
13799  struct nk_rect content, struct nk_color background, struct nk_color foreground,
13800  float border_width, const struct nk_user_font *font)
13801 {
13802  switch (type) {
13803  case NK_SYMBOL_X:
13804  case NK_SYMBOL_UNDERSCORE:
13805  case NK_SYMBOL_PLUS:
13806  case NK_SYMBOL_MINUS: {
13807  /* single character text symbol */
13808  const char *X = (type == NK_SYMBOL_X) ? "x":
13809  (type == NK_SYMBOL_UNDERSCORE) ? "_":
13810  (type == NK_SYMBOL_PLUS) ? "+": "-";
13811  struct nk_text text;
13812  text.padding = nk_vec2(0,0);
13813  text.background = background;
13814  text.text = foreground;
13815  nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
13816  } break;
13819  case NK_SYMBOL_RECT_SOLID:
13820  case NK_SYMBOL_RECT_OUTLINE: {
13821  /* simple empty/filled shapes */
13822  if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
13823  nk_fill_rect(out, content, 0, foreground);
13824  if (type == NK_SYMBOL_RECT_OUTLINE)
13825  nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
13826  } else {
13827  nk_fill_circle(out, content, foreground);
13828  if (type == NK_SYMBOL_CIRCLE_OUTLINE)
13829  nk_fill_circle(out, nk_shrink_rect(content, 1), background);
13830  }
13831  } break;
13832  case NK_SYMBOL_TRIANGLE_UP:
13835  case NK_SYMBOL_TRIANGLE_RIGHT: {
13836  enum nk_heading heading;
13837  struct nk_vec2 points[3];
13838  heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
13839  (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
13840  (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
13841  nk_triangle_from_direction(points, content, 0, 0, heading);
13842  nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
13843  points[2].x, points[2].y, foreground);
13844  } break;
13845  default:
13846  case NK_SYMBOL_NONE:
13847  case NK_SYMBOL_MAX: break;
13848  }
13849 }
13850 
13851 NK_INTERN int
13852 nk_button_behavior(nk_flags *state, struct nk_rect r,
13853  const struct nk_input *i, enum nk_button_behavior behavior)
13854 {
13855  int ret = 0;
13856  nk_widget_state_reset(state);
13857  if (!i) return 0;
13858  if (nk_input_is_mouse_hovering_rect(i, r)) {
13859  *state = NK_WIDGET_STATE_HOVERED;
13861  *state = NK_WIDGET_STATE_ACTIVE;
13863  ret = (behavior != NK_BUTTON_DEFAULT) ?
13865 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
13867 #else
13869 #endif
13870  }
13871  }
13873  *state |= NK_WIDGET_STATE_ENTERED;
13874  else if (nk_input_is_mouse_prev_hovering_rect(i, r))
13875  *state |= NK_WIDGET_STATE_LEFT;
13876  return ret;
13877 }
13878 
13879 NK_INTERN const struct nk_style_item*
13880 nk_draw_button(struct nk_command_buffer *out,
13881  const struct nk_rect *bounds, nk_flags state,
13882  const struct nk_style_button *style)
13883 {
13884  const struct nk_style_item *background;
13885  if (state & NK_WIDGET_STATE_HOVER)
13886  background = &style->hover;
13887  else if (state & NK_WIDGET_STATE_ACTIVED)
13888  background = &style->active;
13889  else background = &style->normal;
13890 
13891  if (background->type == NK_STYLE_ITEM_IMAGE) {
13892  nk_draw_image(out, *bounds, &background->data.image, nk_white);
13893  } else {
13894  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
13895  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
13896  }
13897  return background;
13898 }
13899 
13900 NK_INTERN int
13901 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
13902  const struct nk_style_button *style, const struct nk_input *in,
13903  enum nk_button_behavior behavior, struct nk_rect *content)
13904 {
13905  struct nk_rect bounds;
13906  NK_ASSERT(style);
13907  NK_ASSERT(state);
13908  NK_ASSERT(out);
13909  if (!out || !style)
13910  return nk_false;
13911 
13912  /* calculate button content space */
13913  content->x = r.x + style->padding.x + style->border + style->rounding;
13914  content->y = r.y + style->padding.y + style->border + style->rounding;
13915  content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
13916  content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
13917 
13918  /* execute button behavior */
13919  bounds.x = r.x - style->touch_padding.x;
13920  bounds.y = r.y - style->touch_padding.y;
13921  bounds.w = r.w + 2 * style->touch_padding.x;
13922  bounds.h = r.h + 2 * style->touch_padding.y;
13923  return nk_button_behavior(state, bounds, in, behavior);
13924 }
13925 
13926 NK_INTERN void
13927 nk_draw_button_text(struct nk_command_buffer *out,
13928  const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
13929  const struct nk_style_button *style, const char *txt, int len,
13930  nk_flags text_alignment, const struct nk_user_font *font)
13931 {
13932  struct nk_text text;
13933  const struct nk_style_item *background;
13934  background = nk_draw_button(out, bounds, state, style);
13935 
13936  /* select correct colors/images */
13937  if (background->type == NK_STYLE_ITEM_COLOR)
13938  text.background = background->data.color;
13939  else text.background = style->text_background;
13940  if (state & NK_WIDGET_STATE_HOVER)
13941  text.text = style->text_hover;
13942  else if (state & NK_WIDGET_STATE_ACTIVED)
13943  text.text = style->text_active;
13944  else text.text = style->text_normal;
13945 
13946  text.padding = nk_vec2(0,0);
13947  nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
13948 }
13949 
13950 NK_INTERN int
13951 nk_do_button_text(nk_flags *state,
13952  struct nk_command_buffer *out, struct nk_rect bounds,
13953  const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
13954  const struct nk_style_button *style, const struct nk_input *in,
13955  const struct nk_user_font *font)
13956 {
13957  struct nk_rect content;
13958  int ret = nk_false;
13959 
13960  NK_ASSERT(state);
13961  NK_ASSERT(style);
13962  NK_ASSERT(out);
13963  NK_ASSERT(string);
13964  NK_ASSERT(font);
13965  if (!out || !style || !font || !string)
13966  return nk_false;
13967 
13968  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
13969  if (style->draw_begin) style->draw_begin(out, style->userdata);
13970  nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
13971  if (style->draw_end) style->draw_end(out, style->userdata);
13972  return ret;
13973 }
13974 
13975 NK_INTERN void
13976 nk_draw_button_symbol(struct nk_command_buffer *out,
13977  const struct nk_rect *bounds, const struct nk_rect *content,
13978  nk_flags state, const struct nk_style_button *style,
13979  enum nk_symbol_type type, const struct nk_user_font *font)
13980 {
13981  struct nk_color sym, bg;
13982  const struct nk_style_item *background;
13983 
13984  /* select correct colors/images */
13985  background = nk_draw_button(out, bounds, state, style);
13986  if (background->type == NK_STYLE_ITEM_COLOR)
13987  bg = background->data.color;
13988  else bg = style->text_background;
13989 
13990  if (state & NK_WIDGET_STATE_HOVER)
13991  sym = style->text_hover;
13992  else if (state & NK_WIDGET_STATE_ACTIVED)
13993  sym = style->text_active;
13994  else sym = style->text_normal;
13995  nk_draw_symbol(out, type, *content, bg, sym, 1, font);
13996 }
13997 
13998 NK_INTERN int
13999 nk_do_button_symbol(nk_flags *state,
14000  struct nk_command_buffer *out, struct nk_rect bounds,
14001  enum nk_symbol_type symbol, enum nk_button_behavior behavior,
14002  const struct nk_style_button *style, const struct nk_input *in,
14003  const struct nk_user_font *font)
14004 {
14005  int ret;
14006  struct nk_rect content;
14007 
14008  NK_ASSERT(state);
14009  NK_ASSERT(style);
14010  NK_ASSERT(font);
14011  NK_ASSERT(out);
14012  if (!out || !style || !font || !state)
14013  return nk_false;
14014 
14015  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14016  if (style->draw_begin) style->draw_begin(out, style->userdata);
14017  nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
14018  if (style->draw_end) style->draw_end(out, style->userdata);
14019  return ret;
14020 }
14021 
14022 NK_INTERN void
14023 nk_draw_button_image(struct nk_command_buffer *out,
14024  const struct nk_rect *bounds, const struct nk_rect *content,
14025  nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
14026 {
14027  nk_draw_button(out, bounds, state, style);
14028  nk_draw_image(out, *content, img, nk_white);
14029 }
14030 
14031 NK_INTERN int
14032 nk_do_button_image(nk_flags *state,
14033  struct nk_command_buffer *out, struct nk_rect bounds,
14034  struct nk_image img, enum nk_button_behavior b,
14035  const struct nk_style_button *style, const struct nk_input *in)
14036 {
14037  int ret;
14038  struct nk_rect content;
14039 
14040  NK_ASSERT(state);
14041  NK_ASSERT(style);
14042  NK_ASSERT(out);
14043  if (!out || !style || !state)
14044  return nk_false;
14045 
14046  ret = nk_do_button(state, out, bounds, style, in, b, &content);
14047  content.x += style->image_padding.x;
14048  content.y += style->image_padding.y;
14049  content.w -= 2 * style->image_padding.x;
14050  content.h -= 2 * style->image_padding.y;
14051 
14052  if (style->draw_begin) style->draw_begin(out, style->userdata);
14053  nk_draw_button_image(out, &bounds, &content, *state, style, &img);
14054  if (style->draw_end) style->draw_end(out, style->userdata);
14055  return ret;
14056 }
14057 
14058 NK_INTERN void
14059 nk_draw_button_text_symbol(struct nk_command_buffer *out,
14060  const struct nk_rect *bounds, const struct nk_rect *label,
14061  const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
14062  const char *str, int len, enum nk_symbol_type type,
14063  const struct nk_user_font *font)
14064 {
14065  struct nk_color sym;
14066  struct nk_text text;
14067  const struct nk_style_item *background;
14068 
14069  /* select correct background colors/images */
14070  background = nk_draw_button(out, bounds, state, style);
14071  if (background->type == NK_STYLE_ITEM_COLOR)
14072  text.background = background->data.color;
14073  else text.background = style->text_background;
14074 
14075  /* select correct text colors */
14076  if (state & NK_WIDGET_STATE_HOVER) {
14077  sym = style->text_hover;
14078  text.text = style->text_hover;
14079  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14080  sym = style->text_active;
14081  text.text = style->text_active;
14082  } else {
14083  sym = style->text_normal;
14084  text.text = style->text_normal;
14085  }
14086 
14087  text.padding = nk_vec2(0,0);
14088  nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
14089  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14090 }
14091 
14092 NK_INTERN int
14093 nk_do_button_text_symbol(nk_flags *state,
14094  struct nk_command_buffer *out, struct nk_rect bounds,
14095  enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
14096  enum nk_button_behavior behavior, const struct nk_style_button *style,
14097  const struct nk_user_font *font, const struct nk_input *in)
14098 {
14099  int ret;
14100  struct nk_rect tri = {0,0,0,0};
14101  struct nk_rect content;
14102 
14103  NK_ASSERT(style);
14104  NK_ASSERT(out);
14105  NK_ASSERT(font);
14106  if (!out || !style || !font)
14107  return nk_false;
14108 
14109  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14110  tri.y = content.y + (content.h/2) - font->height/2;
14111  tri.w = font->height; tri.h = font->height;
14112  if (align & NK_TEXT_ALIGN_LEFT) {
14113  tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
14114  tri.x = NK_MAX(tri.x, 0);
14115  } else tri.x = content.x + 2 * style->padding.x;
14116 
14117  /* draw button */
14118  if (style->draw_begin) style->draw_begin(out, style->userdata);
14119  nk_draw_button_text_symbol(out, &bounds, &content, &tri,
14120  *state, style, str, len, symbol, font);
14121  if (style->draw_end) style->draw_end(out, style->userdata);
14122  return ret;
14123 }
14124 
14125 NK_INTERN void
14126 nk_draw_button_text_image(struct nk_command_buffer *out,
14127  const struct nk_rect *bounds, const struct nk_rect *label,
14128  const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
14129  const char *str, int len, const struct nk_user_font *font,
14130  const struct nk_image *img)
14131 {
14132  struct nk_text text;
14133  const struct nk_style_item *background;
14134  background = nk_draw_button(out, bounds, state, style);
14135 
14136  /* select correct colors */
14137  if (background->type == NK_STYLE_ITEM_COLOR)
14138  text.background = background->data.color;
14139  else text.background = style->text_background;
14140  if (state & NK_WIDGET_STATE_HOVER)
14141  text.text = style->text_hover;
14142  else if (state & NK_WIDGET_STATE_ACTIVED)
14143  text.text = style->text_active;
14144  else text.text = style->text_normal;
14145 
14146  text.padding = nk_vec2(0,0);
14147  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14148  nk_draw_image(out, *image, img, nk_white);
14149 }
14150 
14151 NK_INTERN int
14152 nk_do_button_text_image(nk_flags *state,
14153  struct nk_command_buffer *out, struct nk_rect bounds,
14154  struct nk_image img, const char* str, int len, nk_flags align,
14155  enum nk_button_behavior behavior, const struct nk_style_button *style,
14156  const struct nk_user_font *font, const struct nk_input *in)
14157 {
14158  int ret;
14159  struct nk_rect icon;
14160  struct nk_rect content;
14161 
14162  NK_ASSERT(style);
14163  NK_ASSERT(state);
14164  NK_ASSERT(font);
14165  NK_ASSERT(out);
14166  if (!out || !font || !style || !str)
14167  return nk_false;
14168 
14169  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14170  icon.y = bounds.y + style->padding.y;
14171  icon.w = icon.h = bounds.h - 2 * style->padding.y;
14172  if (align & NK_TEXT_ALIGN_LEFT) {
14173  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14174  icon.x = NK_MAX(icon.x, 0);
14175  } else icon.x = bounds.x + 2 * style->padding.x;
14176 
14177  icon.x += style->image_padding.x;
14178  icon.y += style->image_padding.y;
14179  icon.w -= 2 * style->image_padding.x;
14180  icon.h -= 2 * style->image_padding.y;
14181 
14182  if (style->draw_begin) style->draw_begin(out, style->userdata);
14183  nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
14184  if (style->draw_end) style->draw_end(out, style->userdata);
14185  return ret;
14186 }
14187 
14188 /* ===============================================================
14189  *
14190  * TOGGLE
14191  *
14192  * ===============================================================*/
14193 enum nk_toggle_type {
14194  NK_TOGGLE_CHECK,
14195  NK_TOGGLE_OPTION
14196 };
14197 
14198 NK_INTERN int
14199 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
14200  nk_flags *state, int active)
14201 {
14202  nk_widget_state_reset(state);
14203  if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
14204  *state = NK_WIDGET_STATE_ACTIVE;
14205  active = !active;
14206  }
14207  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
14208  *state |= NK_WIDGET_STATE_ENTERED;
14209  else if (nk_input_is_mouse_prev_hovering_rect(in, select))
14210  *state |= NK_WIDGET_STATE_LEFT;
14211  return active;
14212 }
14213 
14214 NK_INTERN void
14215 nk_draw_checkbox(struct nk_command_buffer *out,
14216  nk_flags state, const struct nk_style_toggle *style, int active,
14217  const struct nk_rect *label, const struct nk_rect *selector,
14218  const struct nk_rect *cursors, const char *string, int len,
14219  const struct nk_user_font *font)
14220 {
14221  const struct nk_style_item *background;
14222  const struct nk_style_item *cursor;
14223  struct nk_text text;
14224 
14225  /* select correct colors/images */
14226  if (state & NK_WIDGET_STATE_HOVER) {
14227  background = &style->hover;
14228  cursor = &style->cursor_hover;
14229  text.text = style->text_hover;
14230  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14231  background = &style->hover;
14232  cursor = &style->cursor_hover;
14233  text.text = style->text_active;
14234  } else {
14235  background = &style->normal;
14236  cursor = &style->cursor_normal;
14237  text.text = style->text_normal;
14238  }
14239 
14240  /* draw background and cursor */
14241  if (background->type == NK_STYLE_ITEM_COLOR) {
14242  nk_fill_rect(out, *selector, 0, style->border_color);
14243  nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
14244  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14245  if (active) {
14246  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14247  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14248  else nk_fill_rect(out, *cursors, 0, cursor->data.color);
14249  }
14250 
14251  text.padding.x = 0;
14252  text.padding.y = 0;
14253  text.background = style->text_background;
14254  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14255 }
14256 
14257 NK_INTERN void
14258 nk_draw_option(struct nk_command_buffer *out,
14259  nk_flags state, const struct nk_style_toggle *style, int active,
14260  const struct nk_rect *label, const struct nk_rect *selector,
14261  const struct nk_rect *cursors, const char *string, int len,
14262  const struct nk_user_font *font)
14263 {
14264  const struct nk_style_item *background;
14265  const struct nk_style_item *cursor;
14266  struct nk_text text;
14267 
14268  /* select correct colors/images */
14269  if (state & NK_WIDGET_STATE_HOVER) {
14270  background = &style->hover;
14271  cursor = &style->cursor_hover;
14272  text.text = style->text_hover;
14273  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14274  background = &style->hover;
14275  cursor = &style->cursor_hover;
14276  text.text = style->text_active;
14277  } else {
14278  background = &style->normal;
14279  cursor = &style->cursor_normal;
14280  text.text = style->text_normal;
14281  }
14282 
14283  /* draw background and cursor */
14284  if (background->type == NK_STYLE_ITEM_COLOR) {
14285  nk_fill_circle(out, *selector, style->border_color);
14286  nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
14287  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14288  if (active) {
14289  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14290  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14291  else nk_fill_circle(out, *cursors, cursor->data.color);
14292  }
14293 
14294  text.padding.x = 0;
14295  text.padding.y = 0;
14296  text.background = style->text_background;
14297  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14298 }
14299 
14300 NK_INTERN int
14301 nk_do_toggle(nk_flags *state,
14302  struct nk_command_buffer *out, struct nk_rect r,
14303  int *active, const char *str, int len, enum nk_toggle_type type,
14304  const struct nk_style_toggle *style, const struct nk_input *in,
14305  const struct nk_user_font *font)
14306 {
14307  int was_active;
14308  struct nk_rect bounds;
14309  struct nk_rect select;
14310  struct nk_rect cursor;
14311  struct nk_rect label;
14312 
14313  NK_ASSERT(style);
14314  NK_ASSERT(out);
14315  NK_ASSERT(font);
14316  if (!out || !style || !font || !active)
14317  return 0;
14318 
14319  r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
14320  r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
14321 
14322  /* add additional touch padding for touch screen devices */
14323  bounds.x = r.x - style->touch_padding.x;
14324  bounds.y = r.y - style->touch_padding.y;
14325  bounds.w = r.w + 2 * style->touch_padding.x;
14326  bounds.h = r.h + 2 * style->touch_padding.y;
14327 
14328  /* calculate the selector space */
14329  select.w = font->height;
14330  select.h = select.w;
14331  select.y = r.y + r.h/2.0f - select.h/2.0f;
14332  select.x = r.x;
14333 
14334  /* calculate the bounds of the cursor inside the selector */
14335  cursor.x = select.x + style->padding.x + style->border;
14336  cursor.y = select.y + style->padding.y + style->border;
14337  cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
14338  cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
14339 
14340  /* label behind the selector */
14341  label.x = select.x + select.w + style->spacing;
14342  label.y = select.y;
14343  label.w = NK_MAX(r.x + r.w, label.x) - label.x;
14344  label.h = select.w;
14345 
14346  /* update selector */
14347  was_active = *active;
14348  *active = nk_toggle_behavior(in, bounds, state, *active);
14349 
14350  /* draw selector */
14351  if (style->draw_begin)
14352  style->draw_begin(out, style->userdata);
14353  if (type == NK_TOGGLE_CHECK) {
14354  nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14355  } else {
14356  nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14357  }
14358  if (style->draw_end)
14359  style->draw_end(out, style->userdata);
14360  return (was_active != *active);
14361 }
14362 
14363 /* ===============================================================
14364  *
14365  * SELECTABLE
14366  *
14367  * ===============================================================*/
14368 NK_INTERN void
14369 nk_draw_selectable(struct nk_command_buffer *out,
14370  nk_flags state, const struct nk_style_selectable *style, int active,
14371  const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img,
14372  const char *string, int len, nk_flags align, const struct nk_user_font *font)
14373 {
14374  const struct nk_style_item *background;
14375  struct nk_text text;
14376  text.padding = style->padding;
14377 
14378  /* select correct colors/images */
14379  if (!active) {
14380  if (state & NK_WIDGET_STATE_ACTIVED) {
14381  background = &style->pressed;
14382  text.text = style->text_pressed;
14383  } else if (state & NK_WIDGET_STATE_HOVER) {
14384  background = &style->hover;
14385  text.text = style->text_hover;
14386  } else {
14387  background = &style->normal;
14388  text.text = style->text_normal;
14389  }
14390  } else {
14391  if (state & NK_WIDGET_STATE_ACTIVED) {
14392  background = &style->pressed_active;
14393  text.text = style->text_pressed_active;
14394  } else if (state & NK_WIDGET_STATE_HOVER) {
14395  background = &style->hover_active;
14396  text.text = style->text_hover_active;
14397  } else {
14398  background = &style->normal_active;
14399  text.text = style->text_normal_active;
14400  }
14401  }
14402 
14403 
14404  /* draw selectable background and text */
14405  if (background->type == NK_STYLE_ITEM_IMAGE) {
14406  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14407  text.background = nk_rgba(0,0,0,0);
14408  } else {
14409  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14410  text.background = background->data.color;
14411  }
14412  if (img && icon) nk_draw_image(out, *icon, img, nk_white);
14413  nk_widget_text(out, *bounds, string, len, &text, align, font);
14414 }
14415 
14416 NK_INTERN int
14417 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
14418  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14419  const struct nk_style_selectable *style, const struct nk_input *in,
14420  const struct nk_user_font *font)
14421 {
14422  int old_value;
14423  struct nk_rect touch;
14424 
14425  NK_ASSERT(state);
14426  NK_ASSERT(out);
14427  NK_ASSERT(str);
14428  NK_ASSERT(len);
14429  NK_ASSERT(value);
14430  NK_ASSERT(style);
14431  NK_ASSERT(font);
14432 
14433  if (!state || !out || !str || !len || !value || !style || !font) return 0;
14434  old_value = *value;
14435 
14436  /* remove padding */
14437  touch.x = bounds.x - style->touch_padding.x;
14438  touch.y = bounds.y - style->touch_padding.y;
14439  touch.w = bounds.w + style->touch_padding.x * 2;
14440  touch.h = bounds.h + style->touch_padding.y * 2;
14441 
14442  /* update button */
14443  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
14444  *value = !(*value);
14445 
14446  /* draw selectable */
14447  if (style->draw_begin) style->draw_begin(out, style->userdata);
14448  nk_draw_selectable(out, *state, style, *value, &bounds, 0,0, str, len, align, font);
14449  if (style->draw_end) style->draw_end(out, style->userdata);
14450  return old_value != *value;
14451 }
14452 
14453 NK_INTERN int
14454 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
14455  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14456  const struct nk_image *img, const struct nk_style_selectable *style,
14457  const struct nk_input *in, const struct nk_user_font *font)
14458 {
14459  int old_value;
14460  struct nk_rect touch;
14461  struct nk_rect icon;
14462 
14463  NK_ASSERT(state);
14464  NK_ASSERT(out);
14465  NK_ASSERT(str);
14466  NK_ASSERT(len);
14467  NK_ASSERT(value);
14468  NK_ASSERT(style);
14469  NK_ASSERT(font);
14470 
14471  if (!state || !out || !str || !len || !value || !style || !font) return 0;
14472  old_value = *value;
14473 
14474  /* toggle behavior */
14475  touch.x = bounds.x - style->touch_padding.x;
14476  touch.y = bounds.y - style->touch_padding.y;
14477  touch.w = bounds.w + style->touch_padding.x * 2;
14478  touch.h = bounds.h + style->touch_padding.y * 2;
14479  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
14480  *value = !(*value);
14481 
14482  icon.y = bounds.y + style->padding.y;
14483  icon.w = icon.h = bounds.h - 2 * style->padding.y;
14484  if (align & NK_TEXT_ALIGN_LEFT) {
14485  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14486  icon.x = NK_MAX(icon.x, 0);
14487  } else icon.x = bounds.x + 2 * style->padding.x;
14488 
14489  icon.x += style->image_padding.x;
14490  icon.y += style->image_padding.y;
14491  icon.w -= 2 * style->image_padding.x;
14492  icon.h -= 2 * style->image_padding.y;
14493 
14494  /* draw selectable */
14495  if (style->draw_begin) style->draw_begin(out, style->userdata);
14496  nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, str, len, align, font);
14497  if (style->draw_end) style->draw_end(out, style->userdata);
14498  return old_value != *value;
14499 }
14500 
14501 
14502 /* ===============================================================
14503  *
14504  * SLIDER
14505  *
14506  * ===============================================================*/
14507 NK_INTERN float
14508 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
14509  struct nk_rect *visual_cursor, struct nk_input *in,
14510  struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
14511  float slider_step, float slider_steps)
14512 {
14513  int left_mouse_down;
14514  int left_mouse_click_in_cursor;
14515 
14516  /* check if visual cursor is being dragged */
14517  nk_widget_state_reset(state);
14518  left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
14519  left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
14520  NK_BUTTON_LEFT, *visual_cursor, nk_true);
14521 
14522  if (left_mouse_down && left_mouse_click_in_cursor)
14523  {
14524  float ratio = 0;
14525  const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
14526  const float pxstep = bounds.w / slider_steps;
14527 
14528  /* only update value if the next slider step is reached */
14529  *state = NK_WIDGET_STATE_ACTIVE;
14530  if (NK_ABS(d) >= pxstep) {
14531  const float steps = (float)((int)(NK_ABS(d) / pxstep));
14532  slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
14533  slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
14534  ratio = (slider_value - slider_min)/slider_step;
14535  logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
14536  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
14537  }
14538  }
14539 
14540  /* slider widget state */
14541  if (nk_input_is_mouse_hovering_rect(in, bounds))
14542  *state = NK_WIDGET_STATE_HOVERED;
14543  if (*state & NK_WIDGET_STATE_HOVER &&
14545  *state |= NK_WIDGET_STATE_ENTERED;
14546  else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
14547  *state |= NK_WIDGET_STATE_LEFT;
14548  return slider_value;
14549 }
14550 
14551 NK_INTERN void
14552 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
14553  const struct nk_style_slider *style, const struct nk_rect *bounds,
14554  const struct nk_rect *visual_cursor, float min, float value, float max)
14555 {
14556  struct nk_rect fill;
14557  struct nk_rect bar;
14558  const struct nk_style_item *background;
14559 
14560  /* select correct slider images/colors */
14561  struct nk_color bar_color;
14562  const struct nk_style_item *cursor;
14563 
14564  NK_UNUSED(min);
14565  NK_UNUSED(max);
14566  NK_UNUSED(value);
14567 
14568  if (state & NK_WIDGET_STATE_ACTIVED) {
14569  background = &style->active;
14570  bar_color = style->bar_active;
14571  cursor = &style->cursor_active;
14572  } else if (state & NK_WIDGET_STATE_HOVER) {
14573  background = &style->hover;
14574  bar_color = style->bar_hover;
14575  cursor = &style->cursor_hover;
14576  } else {
14577  background = &style->normal;
14578  bar_color = style->bar_normal;
14579  cursor = &style->cursor_normal;
14580  }
14581 
14582  /* calculate slider background bar */
14583  bar.x = bounds->x;
14584  bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
14585  bar.w = bounds->w;
14586  bar.h = bounds->h/6;
14587 
14588  /* filled background bar style */
14589  fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
14590  fill.x = bar.x;
14591  fill.y = bar.y;
14592  fill.h = bar.h;
14593 
14594  /* draw background */
14595  if (background->type == NK_STYLE_ITEM_IMAGE) {
14596  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14597  } else {
14598  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14599  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14600  }
14601 
14602  /* draw slider bar */
14603  nk_fill_rect(out, bar, style->rounding, bar_color);
14604  nk_fill_rect(out, fill, style->rounding, style->bar_filled);
14605 
14606  /* draw cursor */
14607  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14608  nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
14609  else nk_fill_circle(out, *visual_cursor, cursor->data.color);
14610 }
14611 
14612 NK_INTERN float
14613 nk_do_slider(nk_flags *state,
14614  struct nk_command_buffer *out, struct nk_rect bounds,
14615  float min, float val, float max, float step,
14616  const struct nk_style_slider *style, struct nk_input *in,
14617  const struct nk_user_font *font)
14618 {
14619  float slider_range;
14620  float slider_min;
14621  float slider_max;
14622  float slider_value;
14623  float slider_steps;
14624  float cursor_offset;
14625 
14626  struct nk_rect visual_cursor;
14627  struct nk_rect logical_cursor;
14628 
14629  NK_ASSERT(style);
14630  NK_ASSERT(out);
14631  if (!out || !style)
14632  return 0;
14633 
14634  /* remove padding from slider bounds */
14635  bounds.x = bounds.x + style->padding.x;
14636  bounds.y = bounds.y + style->padding.y;
14637  bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
14638  bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
14639  bounds.w -= 2 * style->padding.x;
14640  bounds.h -= 2 * style->padding.y;
14641 
14642  /* optional buttons */
14643  if (style->show_buttons) {
14644  nk_flags ws;
14645  struct nk_rect button;
14646  button.y = bounds.y;
14647  button.w = bounds.h;
14648  button.h = bounds.h;
14649 
14650  /* decrement button */
14651  button.x = bounds.x;
14652  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
14653  &style->dec_button, in, font))
14654  val -= step;
14655 
14656  /* increment button */
14657  button.x = (bounds.x + bounds.w) - button.w;
14658  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
14659  &style->inc_button, in, font))
14660  val += step;
14661 
14662  bounds.x = bounds.x + button.w + style->spacing.x;
14663  bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
14664  }
14665 
14666  /* remove one cursor size to support visual cursor */
14667  bounds.x += style->cursor_size.x*0.5f;
14668  bounds.w -= style->cursor_size.x;
14669 
14670  /* make sure the provided values are correct */
14671  slider_max = NK_MAX(min, max);
14672  slider_min = NK_MIN(min, max);
14673  slider_value = NK_CLAMP(slider_min, val, slider_max);
14674  slider_range = slider_max - slider_min;
14675  slider_steps = slider_range / step;
14676  cursor_offset = (slider_value - slider_min) / step;
14677 
14678  /* calculate cursor
14679  Basically you have two cursors. One for visual representation and interaction
14680  and one for updating the actual cursor value. */
14681  logical_cursor.h = bounds.h;
14682  logical_cursor.w = bounds.w / slider_steps;
14683  logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
14684  logical_cursor.y = bounds.y;
14685 
14686  visual_cursor.h = style->cursor_size.y;
14687  visual_cursor.w = style->cursor_size.x;
14688  visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
14689  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14690 
14691  slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
14692  in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
14693  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14694 
14695  /* draw slider */
14696  if (style->draw_begin) style->draw_begin(out, style->userdata);
14697  nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
14698  if (style->draw_end) style->draw_end(out, style->userdata);
14699  return slider_value;
14700 }
14701 
14702 /* ===============================================================
14703  *
14704  * PROGRESSBAR
14705  *
14706  * ===============================================================*/
14707 NK_INTERN nk_size
14708 nk_progress_behavior(nk_flags *state, const struct nk_input *in,
14709  struct nk_rect r, nk_size max, nk_size value, int modifiable)
14710 {
14711  nk_widget_state_reset(state);
14712  if (in && modifiable && nk_input_is_mouse_hovering_rect(in, r)) {
14713  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
14714  int left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
14715  NK_BUTTON_LEFT, r, nk_true);
14716 
14717  if (left_mouse_down && left_mouse_click_in_cursor) {
14718  float ratio = NK_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w;
14719  value = (nk_size)NK_MAX(0,((float)max * ratio));
14720  *state = NK_WIDGET_STATE_ACTIVE;
14721  } else *state = NK_WIDGET_STATE_HOVERED;
14722  }
14723 
14724  /* set progressbar widget state */
14725  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
14726  *state |= NK_WIDGET_STATE_ENTERED;
14727  else if (nk_input_is_mouse_prev_hovering_rect(in, r))
14728  *state |= NK_WIDGET_STATE_LEFT;
14729 
14730  if (!max) return value;
14731  value = NK_MIN(value, max);
14732  return value;
14733 }
14734 
14735 NK_INTERN void
14736 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
14737  const struct nk_style_progress *style, const struct nk_rect *bounds,
14738  const struct nk_rect *scursor, nk_size value, nk_size max)
14739 {
14740  const struct nk_style_item *background;
14741  const struct nk_style_item *cursor;
14742 
14743  NK_UNUSED(max);
14744  NK_UNUSED(value);
14745 
14746  /* select correct colors/images to draw */
14747  if (state & NK_WIDGET_STATE_ACTIVED) {
14748  background = &style->active;
14749  cursor = &style->cursor_active;
14750  } else if (state & NK_WIDGET_STATE_HOVER){
14751  background = &style->hover;
14752  cursor = &style->cursor_hover;
14753  } else {
14754  background = &style->normal;
14755  cursor = &style->cursor_normal;
14756  }
14757 
14758  /* draw background */
14759  if (background->type == NK_STYLE_ITEM_COLOR) {
14760  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14761  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14762  } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
14763 
14764  /* draw cursor */
14765  if (background->type == NK_STYLE_ITEM_COLOR) {
14766  nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
14767  nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
14768  } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
14769 }
14770 
14771 NK_INTERN nk_size
14772 nk_do_progress(nk_flags *state,
14773  struct nk_command_buffer *out, struct nk_rect bounds,
14774  nk_size value, nk_size max, int modifiable,
14775  const struct nk_style_progress *style, const struct nk_input *in)
14776 {
14777  float prog_scale;
14778  nk_size prog_value;
14779  struct nk_rect cursor;
14780 
14781  NK_ASSERT(style);
14782  NK_ASSERT(out);
14783  if (!out || !style) return 0;
14784 
14785  /* calculate progressbar cursor */
14786  cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
14787  cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
14788  cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
14789  prog_scale = (float)value / (float)max;
14790  cursor.w = (bounds.w - 2) * prog_scale;
14791 
14792  /* update progressbar */
14793  prog_value = NK_MIN(value, max);
14794  prog_value = nk_progress_behavior(state, in, bounds, max, prog_value, modifiable);
14795 
14796  /* draw progressbar */
14797  if (style->draw_begin) style->draw_begin(out, style->userdata);
14798  nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
14799  if (style->draw_end) style->draw_end(out, style->userdata);
14800  return prog_value;
14801 }
14802 
14803 /* ===============================================================
14804  *
14805  * SCROLLBAR
14806  *
14807  * ===============================================================*/
14808 NK_INTERN float
14809 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
14810  int has_scrolling, const struct nk_rect *scroll,
14811  const struct nk_rect *cursor, const struct nk_rect *empty0,
14812  const struct nk_rect *empty1, float scroll_offset,
14813  float target, float scroll_step, enum nk_orientation o)
14814 {
14815  nk_flags ws = 0;
14816  int left_mouse_down;
14817  int left_mouse_click_in_cursor;
14818  float scroll_delta;
14819 
14820  nk_widget_state_reset(state);
14821  if (!in) return scroll_offset;
14822 
14823  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
14824  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
14825  NK_BUTTON_LEFT, *cursor, nk_true);
14826  if (nk_input_is_mouse_hovering_rect(in, *scroll))
14827  *state = NK_WIDGET_STATE_HOVERED;
14828 
14829  scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
14830  if (left_mouse_down && left_mouse_click_in_cursor) {
14831  /* update cursor by mouse dragging */
14832  float pixel, delta;
14833  *state = NK_WIDGET_STATE_ACTIVE;
14834  if (o == NK_VERTICAL) {
14835  float cursor_y;
14836  pixel = in->mouse.delta.y;
14837  delta = (pixel / scroll->h) * target;
14838  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
14839  cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
14840  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
14841  } else {
14842  float cursor_x;
14843  pixel = in->mouse.delta.x;
14844  delta = (pixel / scroll->w) * target;
14845  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
14846  cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
14847  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
14848  }
14849  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
14850  nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
14851  /* scroll page up by click on empty space or shortcut */
14852  if (o == NK_VERTICAL)
14853  scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
14854  else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
14855  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
14856  nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
14857  /* scroll page down by click on empty space or shortcut */
14858  if (o == NK_VERTICAL)
14859  scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
14860  else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
14861  } else if (has_scrolling) {
14862  if ((scroll_delta < 0 || (scroll_delta > 0))) {
14863  /* update cursor by mouse scrolling */
14864  scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
14865  if (o == NK_VERTICAL)
14866  scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
14867  else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
14868  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
14869  /* update cursor to the beginning */
14870  if (o == NK_VERTICAL) scroll_offset = 0;
14871  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
14872  /* update cursor to the end */
14873  if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
14874  }
14875  }
14876  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
14877  *state |= NK_WIDGET_STATE_ENTERED;
14878  else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
14879  *state |= NK_WIDGET_STATE_LEFT;
14880  return scroll_offset;
14881 }
14882 
14883 NK_INTERN void
14884 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
14885  const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
14886  const struct nk_rect *scroll)
14887 {
14888  const struct nk_style_item *background;
14889  const struct nk_style_item *cursor;
14890 
14891  /* select correct colors/images to draw */
14892  if (state & NK_WIDGET_STATE_ACTIVED) {
14893  background = &style->active;
14894  cursor = &style->cursor_active;
14895  } else if (state & NK_WIDGET_STATE_HOVER) {
14896  background = &style->hover;
14897  cursor = &style->cursor_hover;
14898  } else {
14899  background = &style->normal;
14900  cursor = &style->cursor_normal;
14901  }
14902 
14903  /* draw background */
14904  if (background->type == NK_STYLE_ITEM_COLOR) {
14905  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14906  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14907  } else {
14908  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14909  }
14910 
14911  /* draw cursor */
14912  if (background->type == NK_STYLE_ITEM_COLOR) {
14913  nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
14914  nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
14915  } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
14916 }
14917 
14918 NK_INTERN float
14919 nk_do_scrollbarv(nk_flags *state,
14920  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
14921  float offset, float target, float step, float button_pixel_inc,
14922  const struct nk_style_scrollbar *style, struct nk_input *in,
14923  const struct nk_user_font *font)
14924 {
14925  struct nk_rect empty_north;
14926  struct nk_rect empty_south;
14927  struct nk_rect cursor;
14928 
14929  float scroll_step;
14930  float scroll_offset;
14931  float scroll_off;
14932  float scroll_ratio;
14933 
14934  NK_ASSERT(out);
14935  NK_ASSERT(style);
14936  NK_ASSERT(state);
14937  if (!out || !style) return 0;
14938 
14939  scroll.w = NK_MAX(scroll.w, 1);
14940  scroll.h = NK_MAX(scroll.h, 0);
14941  if (target <= scroll.h) return 0;
14942 
14943  /* optional scrollbar buttons */
14944  if (style->show_buttons) {
14945  nk_flags ws;
14946  float scroll_h;
14947  struct nk_rect button;
14948 
14949  button.x = scroll.x;
14950  button.w = scroll.w;
14951  button.h = scroll.w;
14952 
14953  scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
14954  scroll_step = NK_MIN(step, button_pixel_inc);
14955 
14956  /* decrement button */
14957  button.y = scroll.y;
14958  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
14959  NK_BUTTON_REPEATER, &style->dec_button, in, font))
14960  offset = offset - scroll_step;
14961 
14962  /* increment button */
14963  button.y = scroll.y + scroll.h - button.h;
14964  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
14965  NK_BUTTON_REPEATER, &style->inc_button, in, font))
14966  offset = offset + scroll_step;
14967 
14968  scroll.y = scroll.y + button.h;
14969  scroll.h = scroll_h;
14970  }
14971 
14972  /* calculate scrollbar constants */
14973  scroll_step = NK_MIN(step, scroll.h);
14974  scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
14975  scroll_ratio = scroll.h / target;
14976  scroll_off = scroll_offset / target;
14977 
14978  /* calculate scrollbar cursor bounds */
14979  cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
14980  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
14981  cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
14982  cursor.x = scroll.x + style->border + style->padding.x;
14983 
14984  /* calculate empty space around cursor */
14985  empty_north.x = scroll.x;
14986  empty_north.y = scroll.y;
14987  empty_north.w = scroll.w;
14988  empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
14989 
14990  empty_south.x = scroll.x;
14991  empty_south.y = cursor.y + cursor.h;
14992  empty_south.w = scroll.w;
14993  empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
14994 
14995  /* update scrollbar */
14996  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
14997  &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
14998  scroll_off = scroll_offset / target;
14999  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
15000 
15001  /* draw scrollbar */
15002  if (style->draw_begin) style->draw_begin(out, style->userdata);
15003  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15004  if (style->draw_end) style->draw_end(out, style->userdata);
15005  return scroll_offset;
15006 }
15007 
15008 NK_INTERN float
15009 nk_do_scrollbarh(nk_flags *state,
15010  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
15011  float offset, float target, float step, float button_pixel_inc,
15012  const struct nk_style_scrollbar *style, struct nk_input *in,
15013  const struct nk_user_font *font)
15014 {
15015  struct nk_rect cursor;
15016  struct nk_rect empty_west;
15017  struct nk_rect empty_east;
15018 
15019  float scroll_step;
15020  float scroll_offset;
15021  float scroll_off;
15022  float scroll_ratio;
15023 
15024  NK_ASSERT(out);
15025  NK_ASSERT(style);
15026  if (!out || !style) return 0;
15027 
15028  /* scrollbar background */
15029  scroll.h = NK_MAX(scroll.h, 1);
15030  scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
15031  if (target <= scroll.w) return 0;
15032 
15033  /* optional scrollbar buttons */
15034  if (style->show_buttons) {
15035  nk_flags ws;
15036  float scroll_w;
15037  struct nk_rect button;
15038  button.y = scroll.y;
15039  button.w = scroll.h;
15040  button.h = scroll.h;
15041 
15042  scroll_w = scroll.w - 2 * button.w;
15043  scroll_step = NK_MIN(step, button_pixel_inc);
15044 
15045  /* decrement button */
15046  button.x = scroll.x;
15047  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
15048  NK_BUTTON_REPEATER, &style->dec_button, in, font))
15049  offset = offset - scroll_step;
15050 
15051  /* increment button */
15052  button.x = scroll.x + scroll.w - button.w;
15053  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
15054  NK_BUTTON_REPEATER, &style->inc_button, in, font))
15055  offset = offset + scroll_step;
15056 
15057  scroll.x = scroll.x + button.w;
15058  scroll.w = scroll_w;
15059  }
15060 
15061  /* calculate scrollbar constants */
15062  scroll_step = NK_MIN(step, scroll.w);
15063  scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
15064  scroll_ratio = scroll.w / target;
15065  scroll_off = scroll_offset / target;
15066 
15067  /* calculate cursor bounds */
15068  cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
15069  cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
15070  cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
15071  cursor.y = scroll.y + style->border + style->padding.y;
15072 
15073  /* calculate empty space around cursor */
15074  empty_west.x = scroll.x;
15075  empty_west.y = scroll.y;
15076  empty_west.w = cursor.x - scroll.x;
15077  empty_west.h = scroll.h;
15078 
15079  empty_east.x = cursor.x + cursor.w;
15080  empty_east.y = scroll.y;
15081  empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
15082  empty_east.h = scroll.h;
15083 
15084  /* update scrollbar */
15085  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
15086  &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
15087  scroll_off = scroll_offset / target;
15088  cursor.x = scroll.x + (scroll_off * scroll.w);
15089 
15090  /* draw scrollbar */
15091  if (style->draw_begin) style->draw_begin(out, style->userdata);
15092  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15093  if (style->draw_end) style->draw_end(out, style->userdata);
15094  return scroll_offset;
15095 }
15096 
15097 /* ===============================================================
15098  *
15099  * FILTER
15100  *
15101  * ===============================================================*/
15102 NK_API int nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
15103 {(void)unicode;NK_UNUSED(box);return nk_true;}
15104 
15105 NK_API int
15106 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
15107 {
15108  NK_UNUSED(box);
15109  if (unicode > 128) return nk_false;
15110  else return nk_true;
15111 }
15112 
15113 NK_API int
15114 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
15115 {
15116  NK_UNUSED(box);
15117  if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
15118  return nk_false;
15119  else return nk_true;
15120 }
15121 
15122 NK_API int
15123 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
15124 {
15125  NK_UNUSED(box);
15126  if ((unicode < '0' || unicode > '9') && unicode != '-')
15127  return nk_false;
15128  else return nk_true;
15129 }
15130 
15131 NK_API int
15132 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
15133 {
15134  NK_UNUSED(box);
15135  if ((unicode < '0' || unicode > '9') &&
15136  (unicode < 'a' || unicode > 'f') &&
15137  (unicode < 'A' || unicode > 'F'))
15138  return nk_false;
15139  else return nk_true;
15140 }
15141 
15142 NK_API int
15143 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
15144 {
15145  NK_UNUSED(box);
15146  if (unicode < '0' || unicode > '7')
15147  return nk_false;
15148  else return nk_true;
15149 }
15150 
15151 NK_API int
15152 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
15153 {
15154  NK_UNUSED(box);
15155  if (unicode != '0' && unicode != '1')
15156  return nk_false;
15157  else return nk_true;
15158 }
15159 
15160 /* ===============================================================
15161  *
15162  * EDIT
15163  *
15164  * ===============================================================*/
15165 NK_INTERN void
15166 nk_edit_draw_text(struct nk_command_buffer *out,
15167  const struct nk_style_edit *style, float pos_x, float pos_y,
15168  float x_offset, const char *text, int byte_len, float row_height,
15169  const struct nk_user_font *font, struct nk_color background,
15170  struct nk_color foreground, int is_selected)
15171 {
15172  NK_ASSERT(out);
15173  NK_ASSERT(font);
15174  NK_ASSERT(style);
15175  if (!text || !byte_len || !out || !style) return;
15176 
15177  {int glyph_len = 0;
15178  nk_rune unicode = 0;
15179  int text_len = 0;
15180  float line_width = 0;
15181  float glyph_width;
15182  const char *line = text;
15183  float line_offset = 0;
15184  int line_count = 0;
15185 
15186  struct nk_text txt;
15187  txt.padding = nk_vec2(0,0);
15188  txt.background = background;
15189  txt.text = foreground;
15190 
15191  glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
15192  if (!glyph_len) return;
15193  while ((text_len < byte_len) && glyph_len)
15194  {
15195  if (unicode == '\n') {
15196  /* new line sepeator so draw previous line */
15197  struct nk_rect label;
15198  label.y = pos_y + line_offset;
15199  label.h = row_height;
15200  label.w = line_width;
15201  label.x = pos_x;
15202  if (!line_count)
15203  label.x += x_offset;
15204 
15205  if (is_selected) /* selection needs to draw different background color */
15206  nk_fill_rect(out, label, 0, background);
15207  nk_widget_text(out, label, line, (int)((text + text_len) - line),
15208  &txt, NK_TEXT_CENTERED, font);
15209 
15210  text_len++;
15211  line_count++;
15212  line_width = 0;
15213  line = text + text_len;
15214  line_offset += row_height;
15215  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
15216  continue;
15217  }
15218  if (unicode == '\r') {
15219  text_len++;
15220  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15221  continue;
15222  }
15223  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15224  line_width += (float)glyph_width;
15225  text_len += glyph_len;
15226  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15227  continue;
15228  }
15229  if (line_width > 0) {
15230  /* draw last line */
15231  struct nk_rect label;
15232  label.y = pos_y + line_offset;
15233  label.h = row_height;
15234  label.w = line_width;
15235  label.x = pos_x;
15236  if (!line_count)
15237  label.x += x_offset;
15238 
15239  if (is_selected)
15240  nk_fill_rect(out, label, 0, background);
15241  nk_widget_text(out, label, line, (int)((text + text_len) - line),
15242  &txt, NK_TEXT_LEFT, font);
15243  }}
15244 }
15245 
15246 NK_INTERN nk_flags
15247 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
15248  struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
15249  struct nk_text_edit *edit, const struct nk_style_edit *style,
15250  struct nk_input *in, const struct nk_user_font *font)
15251 {
15252  struct nk_rect area;
15253  nk_flags ret = 0;
15254  float row_height;
15255  char prev_state = 0;
15256  char is_hovered = 0;
15257  char select_all = 0;
15258  char cursor_follow = 0;
15259  struct nk_rect old_clip;
15260  struct nk_rect clip;
15261 
15262  NK_ASSERT(state);
15263  NK_ASSERT(out);
15264  NK_ASSERT(style);
15265  if (!state || !out || !style)
15266  return ret;
15267 
15268  /* visible text area calculation */
15269  area.x = bounds.x + style->padding.x + style->border;
15270  area.y = bounds.y + style->padding.y + style->border;
15271  area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
15272  area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
15273  if (flags & NK_EDIT_MULTILINE)
15274  area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
15275  row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
15276 
15277  /* calculate clipping rectangle */
15278  old_clip = out->clip;
15279  nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
15280 
15281  /* update edit state */
15282  prev_state = (char)edit->active;
15283  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
15285  edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
15286  bounds.x, bounds.y, bounds.w, bounds.h);
15287  }
15288 
15289  /* (de)activate text editor */
15290  if (!prev_state && edit->active) {
15291  const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
15293  nk_textedit_clear_state(edit, type, filter);
15294  if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
15296  if (flags & NK_EDIT_AUTO_SELECT)
15297  select_all = nk_true;
15298  if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
15299  edit->cursor = edit->string.len;
15300  in = 0;
15301  }
15302  } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15303  if (flags & NK_EDIT_READ_ONLY)
15304  edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15305 
15306  ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
15307  if (prev_state != edit->active)
15308  ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
15309 
15310  /* handle user input */
15311  if (edit->active && in)
15312  {
15313  int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
15314  const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
15315  const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
15316 
15317  /* mouse click handler */
15318  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
15319  if (select_all) {
15320  nk_textedit_select_all(edit);
15321  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15323  nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
15324  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15325  (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
15326  nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
15327  cursor_follow = nk_true;
15328  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
15330  nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
15331  nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
15332  cursor_follow = nk_true;
15333  }
15334 
15335  {int i; /* keyboard input */
15336  int old_mode = edit->mode;
15337  for (i = 0; i < NK_KEY_MAX; ++i) {
15338  if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
15339  if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
15340  nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
15341  cursor_follow = nk_true;
15342  }
15343  }
15344  if (old_mode != edit->mode) {
15345  in->keyboard.text_len = 0;
15346  }}
15347 
15348  /* text input */
15349  edit->filter = filter;
15350  if (in->keyboard.text_len) {
15352  cursor_follow = nk_true;
15353  in->keyboard.text_len = 0;
15354  }
15355 
15356  /* enter key handler */
15358  cursor_follow = nk_true;
15359  if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
15360  nk_textedit_text(edit, "\n", 1);
15361  else if (flags & NK_EDIT_SIG_ENTER)
15362  ret |= NK_EDIT_COMMITED;
15363  else nk_textedit_text(edit, "\n", 1);
15364  }
15365 
15366  /* cut & copy handler */
15367  {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
15368  int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
15369  if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
15370  {
15371  int glyph_len;
15372  nk_rune unicode;
15373  const char *text;
15374  int b = edit->select_start;
15375  int e = edit->select_end;
15376 
15377  int begin = NK_MIN(b, e);
15378  int end = NK_MAX(b, e);
15379  text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
15380  if (edit->clip.copy)
15381  edit->clip.copy(edit->clip.userdata, text, end - begin);
15382  if (cut && !(flags & NK_EDIT_READ_ONLY)){
15383  nk_textedit_cut(edit);
15384  cursor_follow = nk_true;
15385  }
15386  }}
15387 
15388  /* paste handler */
15389  {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
15390  if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
15391  edit->clip.paste(edit->clip.userdata, edit);
15392  cursor_follow = nk_true;
15393  }}
15394 
15395  /* tab handler */
15396  {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
15397  if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
15398  nk_textedit_text(edit, " ", 4);
15399  cursor_follow = nk_true;
15400  }}
15401  }
15402 
15403  /* set widget state */
15404  if (edit->active)
15405  *state = NK_WIDGET_STATE_ACTIVE;
15406  else nk_widget_state_reset(state);
15407 
15408  if (is_hovered)
15409  *state |= NK_WIDGET_STATE_HOVERED;
15410 
15411  /* DRAW EDIT */
15412  {const char *text = nk_str_get_const(&edit->string);
15413  int len = nk_str_len_char(&edit->string);
15414 
15415  {/* select background colors/images */
15416  const struct nk_style_item *background;
15417  if (*state & NK_WIDGET_STATE_ACTIVED)
15418  background = &style->active;
15419  else if (*state & NK_WIDGET_STATE_HOVER)
15420  background = &style->hover;
15421  else background = &style->normal;
15422 
15423  /* draw background frame */
15424  if (background->type == NK_STYLE_ITEM_COLOR) {
15425  nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
15426  nk_fill_rect(out, bounds, style->rounding, background->data.color);
15427  } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
15428 
15429  area.w = NK_MAX(0, area.w - style->cursor_size);
15430  if (edit->active)
15431  {
15432  int total_lines = 1;
15433  struct nk_vec2 text_size = nk_vec2(0,0);
15434 
15435  /* text pointer positions */
15436  const char *cursor_ptr = 0;
15437  const char *select_begin_ptr = 0;
15438  const char *select_end_ptr = 0;
15439 
15440  /* 2D pixel positions */
15441  struct nk_vec2 cursor_pos = nk_vec2(0,0);
15442  struct nk_vec2 selection_offset_start = nk_vec2(0,0);
15443  struct nk_vec2 selection_offset_end = nk_vec2(0,0);
15444 
15445  int selection_begin = NK_MIN(edit->select_start, edit->select_end);
15446  int selection_end = NK_MAX(edit->select_start, edit->select_end);
15447 
15448  /* calculate total line count + total space + cursor/selection position */
15449  float line_width = 0.0f;
15450  if (text && len)
15451  {
15452  /* utf8 encoding */
15453  float glyph_width;
15454  int glyph_len = 0;
15455  nk_rune unicode = 0;
15456  int text_len = 0;
15457  int glyphs = 0;
15458  int row_begin = 0;
15459 
15460  glyph_len = nk_utf_decode(text, &unicode, len);
15461  glyph_width = font->width(font->userdata, font->height, text, glyph_len);
15462  line_width = 0;
15463 
15464  /* iterate all lines */
15465  while ((text_len < len) && glyph_len)
15466  {
15467  /* set cursor 2D position and line */
15468  if (!cursor_ptr && glyphs == edit->cursor)
15469  {
15470  int glyph_offset;
15471  struct nk_vec2 out_offset;
15472  struct nk_vec2 row_size;
15473  const char *remaining;
15474 
15475  /* calculate 2d position */
15476  cursor_pos.y = (float)(total_lines-1) * row_height;
15477  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15478  text_len-row_begin, row_height, &remaining,
15479  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15480  cursor_pos.x = row_size.x;
15481  cursor_ptr = text + text_len;
15482  }
15483 
15484  /* set start selection 2D position and line */
15485  if (!select_begin_ptr && edit->select_start != edit->select_end &&
15486  glyphs == selection_begin)
15487  {
15488  int glyph_offset;
15489  struct nk_vec2 out_offset;
15490  struct nk_vec2 row_size;
15491  const char *remaining;
15492 
15493  /* calculate 2d position */
15494  selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
15495  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15496  text_len-row_begin, row_height, &remaining,
15497  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15498  selection_offset_start.x = row_size.x;
15499  select_begin_ptr = text + text_len;
15500  }
15501 
15502  /* set end selection 2D position and line */
15503  if (!select_end_ptr && edit->select_start != edit->select_end &&
15504  glyphs == selection_end)
15505  {
15506  int glyph_offset;
15507  struct nk_vec2 out_offset;
15508  struct nk_vec2 row_size;
15509  const char *remaining;
15510 
15511  /* calculate 2d position */
15512  selection_offset_end.y = (float)(total_lines-1) * row_height;
15513  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15514  text_len-row_begin, row_height, &remaining,
15515  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15516  selection_offset_end.x = row_size.x;
15517  select_end_ptr = text + text_len;
15518  }
15519  if (unicode == '\n') {
15520  text_size.x = NK_MAX(text_size.x, line_width);
15521  total_lines++;
15522  line_width = 0;
15523  text_len++;
15524  glyphs++;
15525  row_begin = text_len;
15526  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15527  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15528  continue;
15529  }
15530 
15531  glyphs++;
15532  text_len += glyph_len;
15533  line_width += (float)glyph_width;
15534 
15535  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15536  glyph_width = font->width(font->userdata, font->height,
15537  text+text_len, glyph_len);
15538  continue;
15539  }
15540  text_size.y = (float)total_lines * row_height;
15541 
15542  /* handle case when cursor is at end of text buffer */
15543  if (!cursor_ptr && edit->cursor == edit->string.len) {
15544  cursor_pos.x = line_width;
15545  cursor_pos.y = text_size.y - row_height;
15546  }
15547  }
15548  {
15549  /* scrollbar */
15550  if (cursor_follow)
15551  {
15552  /* update scrollbar to follow cursor */
15553  if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
15554  /* horizontal scroll */
15555  const float scroll_increment = area.w * 0.25f;
15556  if (cursor_pos.x < edit->scrollbar.x)
15557  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
15558  if (cursor_pos.x >= edit->scrollbar.x + area.w)
15559  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x);
15560  } else edit->scrollbar.x = 0;
15561 
15562  if (flags & NK_EDIT_MULTILINE) {
15563  /* vertical scroll */
15564  if (cursor_pos.y < edit->scrollbar.y)
15565  edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
15566  if (cursor_pos.y >= edit->scrollbar.y + area.h)
15567  edit->scrollbar.y = edit->scrollbar.y + row_height;
15568  } else edit->scrollbar.y = 0;
15569  }
15570 
15571  /* scrollbar widget */
15572  if (flags & NK_EDIT_MULTILINE)
15573  {
15574  nk_flags ws;
15575  struct nk_rect scroll;
15576  float scroll_target;
15577  float scroll_offset;
15578  float scroll_step;
15579  float scroll_inc;
15580 
15581  scroll = area;
15582  scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
15583  scroll.w = style->scrollbar_size.x;
15584 
15585  scroll_offset = edit->scrollbar.y;
15586  scroll_step = scroll.h * 0.10f;
15587  scroll_inc = scroll.h * 0.01f;
15588  scroll_target = text_size.y;
15589  edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
15590  scroll_offset, scroll_target, scroll_step, scroll_inc,
15591  &style->scrollbar, in, font);
15592  }
15593  }
15594 
15595  /* draw text */
15596  {struct nk_color background_color;
15597  struct nk_color text_color;
15598  struct nk_color sel_background_color;
15599  struct nk_color sel_text_color;
15600  struct nk_color cursor_color;
15601  struct nk_color cursor_text_color;
15602  const struct nk_style_item *background;
15603  nk_push_scissor(out, clip);
15604 
15605  /* select correct colors to draw */
15606  if (*state & NK_WIDGET_STATE_ACTIVED) {
15607  background = &style->active;
15608  text_color = style->text_active;
15609  sel_text_color = style->selected_text_hover;
15610  sel_background_color = style->selected_hover;
15611  cursor_color = style->cursor_hover;
15612  cursor_text_color = style->cursor_text_hover;
15613  } else if (*state & NK_WIDGET_STATE_HOVER) {
15614  background = &style->hover;
15615  text_color = style->text_hover;
15616  sel_text_color = style->selected_text_hover;
15617  sel_background_color = style->selected_hover;
15618  cursor_text_color = style->cursor_text_hover;
15619  cursor_color = style->cursor_hover;
15620  } else {
15621  background = &style->normal;
15622  text_color = style->text_normal;
15623  sel_text_color = style->selected_text_normal;
15624  sel_background_color = style->selected_normal;
15625  cursor_color = style->cursor_normal;
15626  cursor_text_color = style->cursor_text_normal;
15627  }
15628  if (background->type == NK_STYLE_ITEM_IMAGE)
15629  background_color = nk_rgba(0,0,0,0);
15630  else background_color = background->data.color;
15631 
15632 
15633  if (edit->select_start == edit->select_end) {
15634  /* no selection so just draw the complete text */
15635  const char *begin = nk_str_get_const(&edit->string);
15636  int l = nk_str_len_char(&edit->string);
15637  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15638  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15639  background_color, text_color, nk_false);
15640  } else {
15641  /* edit has selection so draw 1-3 text chunks */
15642  if (edit->select_start != edit->select_end && selection_begin > 0){
15643  /* draw unselected text before selection */
15644  const char *begin = nk_str_get_const(&edit->string);
15645  NK_ASSERT(select_begin_ptr);
15646  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15647  area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
15648  row_height, font, background_color, text_color, nk_false);
15649  }
15650  if (edit->select_start != edit->select_end) {
15651  /* draw selected text */
15652  NK_ASSERT(select_begin_ptr);
15653  if (!select_end_ptr) {
15654  const char *begin = nk_str_get_const(&edit->string);
15655  select_end_ptr = begin + nk_str_len_char(&edit->string);
15656  }
15657  nk_edit_draw_text(out, style,
15658  area.x - edit->scrollbar.x,
15659  area.y + selection_offset_start.y - edit->scrollbar.y,
15660  selection_offset_start.x,
15661  select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
15662  row_height, font, sel_background_color, sel_text_color, nk_true);
15663  }
15664  if ((edit->select_start != edit->select_end &&
15665  selection_end < edit->string.len))
15666  {
15667  /* draw unselected text after selected text */
15668  const char *begin = select_end_ptr;
15669  const char *end = nk_str_get_const(&edit->string) +
15670  nk_str_len_char(&edit->string);
15671  NK_ASSERT(select_end_ptr);
15672  nk_edit_draw_text(out, style,
15673  area.x - edit->scrollbar.x,
15674  area.y + selection_offset_end.y - edit->scrollbar.y,
15675  selection_offset_end.x,
15676  begin, (int)(end - begin), row_height, font,
15677  background_color, text_color, nk_true);
15678  }
15679  }
15680 
15681  /* cursor */
15682  if (edit->select_start == edit->select_end)
15683  {
15684  if (edit->cursor >= nk_str_len(&edit->string) ||
15685  (cursor_ptr && *cursor_ptr == '\n')) {
15686  /* draw cursor at end of line */
15687  struct nk_rect cursor;
15688  cursor.w = style->cursor_size;
15689  cursor.h = font->height;
15690  cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
15691  cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
15692  cursor.y -= edit->scrollbar.y;
15693  nk_fill_rect(out, cursor, 0, cursor_color);
15694  } else {
15695  /* draw cursor inside text */
15696  int glyph_len;
15697  struct nk_rect label;
15698  struct nk_text txt;
15699 
15700  nk_rune unicode;
15701  NK_ASSERT(cursor_ptr);
15702  glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
15703 
15704  label.x = area.x + cursor_pos.x - edit->scrollbar.x;
15705  label.y = area.y + cursor_pos.y - edit->scrollbar.y;
15706  label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
15707  label.h = row_height;
15708 
15709  txt.padding = nk_vec2(0,0);
15710  txt.background = cursor_color;;
15711  txt.text = cursor_text_color;
15712  nk_fill_rect(out, label, 0, cursor_color);
15713  nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
15714  }
15715  }}
15716  } else {
15717  /* not active so just draw text */
15718  int l = nk_str_len_char(&edit->string);
15719  const char *begin = nk_str_get_const(&edit->string);
15720 
15721  const struct nk_style_item *background;
15722  struct nk_color background_color;
15723  struct nk_color text_color;
15724  nk_push_scissor(out, clip);
15725  if (*state & NK_WIDGET_STATE_ACTIVED) {
15726  background = &style->active;
15727  text_color = style->text_active;
15728  } else if (*state & NK_WIDGET_STATE_HOVER) {
15729  background = &style->hover;
15730  text_color = style->text_hover;
15731  } else {
15732  background = &style->normal;
15733  text_color = style->text_normal;
15734  }
15735  if (background->type == NK_STYLE_ITEM_IMAGE)
15736  background_color = nk_rgba(0,0,0,0);
15737  else background_color = background->data.color;
15738  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15739  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15740  background_color, text_color, nk_false);
15741  }
15742  nk_push_scissor(out, old_clip);}
15743  return ret;
15744 }
15745 
15746 /* ===============================================================
15747  *
15748  * PROPERTY
15749  *
15750  * ===============================================================*/
15751 enum nk_property_status {
15752  NK_PROPERTY_DEFAULT,
15753  NK_PROPERTY_EDIT,
15754  NK_PROPERTY_DRAG
15755 };
15756 enum nk_property_filter {
15757  NK_FILTER_INT,
15758  NK_FILTER_FLOAT
15759 };
15760 enum nk_property_kind {
15761  NK_PROPERTY_INT,
15762  NK_PROPERTY_FLOAT,
15763  NK_PROPERTY_DOUBLE
15764 };
15765 union nk_property {
15766  int i;
15767  float f;
15768  double d;
15769 };
15770 struct nk_property_variant {
15771  enum nk_property_kind kind;
15772  union nk_property value;
15773  union nk_property min_value;
15774  union nk_property max_value;
15775  union nk_property step;
15776 };
15777 
15778 NK_INTERN void
15779 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
15780  struct nk_rect drag, struct nk_property_variant *variant,
15781  float inc_per_pixel)
15782 {
15783  int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
15784  int left_mouse_click_in_cursor = in &&
15786 
15787  nk_widget_state_reset(state);
15788  if (nk_input_is_mouse_hovering_rect(in, drag))
15789  *state = NK_WIDGET_STATE_HOVERED;
15790 
15791  if (left_mouse_down && left_mouse_click_in_cursor) {
15792  float delta, pixels;
15793  pixels = in->mouse.delta.x;
15794  delta = pixels * inc_per_pixel;
15795  switch (variant->kind) {
15796  default: break;
15797  case NK_PROPERTY_INT:
15798  variant->value.i = variant->value.i + (int)delta;
15799  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
15800  break;
15801  case NK_PROPERTY_FLOAT:
15802  variant->value.f = variant->value.f + (float)delta;
15803  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
15804  break;
15805  case NK_PROPERTY_DOUBLE:
15806  variant->value.d = variant->value.d + (double)delta;
15807  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
15808  break;
15809  }
15810  *state = NK_WIDGET_STATE_ACTIVE;
15811  }
15812  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
15813  *state |= NK_WIDGET_STATE_ENTERED;
15814  else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
15815  *state |= NK_WIDGET_STATE_LEFT;
15816 }
15817 
15818 NK_INTERN void
15819 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
15820  struct nk_rect property, struct nk_rect label, struct nk_rect edit,
15821  struct nk_rect empty, int *state, struct nk_property_variant *variant,
15822  float inc_per_pixel)
15823 {
15824  if (in && *state == NK_PROPERTY_DEFAULT) {
15825  if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
15826  *state = NK_PROPERTY_EDIT;
15828  *state = NK_PROPERTY_DRAG;
15830  *state = NK_PROPERTY_DRAG;
15831  }
15832  if (*state == NK_PROPERTY_DRAG) {
15833  nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
15834  if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
15835  }
15836 }
15837 
15838 NK_INTERN void
15839 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
15840  const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
15841  const char *name, int len, const struct nk_user_font *font)
15842 {
15843  struct nk_text text;
15844  const struct nk_style_item *background;
15845 
15846  /* select correct background and text color */
15847  if (state & NK_WIDGET_STATE_ACTIVED) {
15848  background = &style->active;
15849  text.text = style->label_active;
15850  } else if (state & NK_WIDGET_STATE_HOVER) {
15851  background = &style->hover;
15852  text.text = style->label_hover;
15853  } else {
15854  background = &style->normal;
15855  text.text = style->label_normal;
15856  }
15857 
15858  /* draw background */
15859  if (background->type == NK_STYLE_ITEM_IMAGE) {
15860  nk_draw_image(out, *bounds, &background->data.image, nk_white);
15861  text.background = nk_rgba(0,0,0,0);
15862  } else {
15863  text.background = background->data.color;
15864  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
15865  nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
15866  }
15867 
15868  /* draw label */
15869  text.padding = nk_vec2(0,0);
15870  nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
15871 }
15872 
15873 NK_INTERN void
15874 nk_do_property(nk_flags *ws,
15875  struct nk_command_buffer *out, struct nk_rect property,
15876  const char *name, struct nk_property_variant *variant,
15877  float inc_per_pixel, char *buffer, int *len,
15878  int *state, int *cursor, int *select_begin, int *select_end,
15879  const struct nk_style_property *style,
15880  enum nk_property_filter filter, struct nk_input *in,
15881  const struct nk_user_font *font, struct nk_text_edit *text_edit,
15882  enum nk_button_behavior behavior)
15883 {
15884  const nk_plugin_filter filters[] = {
15887  };
15888  int active, old;
15889  int num_len, name_len;
15890  char string[NK_MAX_NUMBER_BUFFER];
15891  float size;
15892 
15893  char *dst = 0;
15894  int *length;
15895 
15896  struct nk_rect left;
15897  struct nk_rect right;
15898  struct nk_rect label;
15899  struct nk_rect edit;
15900  struct nk_rect empty;
15901 
15902  /* left decrement button */
15903  left.h = font->height/2;
15904  left.w = left.h;
15905  left.x = property.x + style->border + style->padding.x;
15906  left.y = property.y + style->border + property.h/2.0f - left.h/2;
15907 
15908  /* text label */
15909  name_len = nk_strlen(name);
15910  size = font->width(font->userdata, font->height, name, name_len);
15911  label.x = left.x + left.w + style->padding.x;
15912  label.w = (float)size + 2 * style->padding.x;
15913  label.y = property.y + style->border + style->padding.y;
15914  label.h = property.h - (2 * style->border + 2 * style->padding.y);
15915 
15916  /* right increment button */
15917  right.y = left.y;
15918  right.w = left.w;
15919  right.h = left.h;
15920  right.x = property.x + property.w - (right.w + style->padding.x);
15921 
15922  /* edit */
15923  if (*state == NK_PROPERTY_EDIT) {
15924  size = font->width(font->userdata, font->height, buffer, *len);
15925  size += style->edit.cursor_size;
15926  length = len;
15927  dst = buffer;
15928  } else {
15929  switch (variant->kind) {
15930  default: break;
15931  case NK_PROPERTY_INT:
15932  nk_itoa(string, variant->value.i);
15933  num_len = nk_strlen(string);
15934  break;
15935  case NK_PROPERTY_FLOAT:
15936  nk_dtoa(string, (double)variant->value.f);
15937  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
15938  break;
15939  case NK_PROPERTY_DOUBLE:
15940  nk_dtoa(string, variant->value.d);
15941  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
15942  break;
15943  }
15944  size = font->width(font->userdata, font->height, string, num_len);
15945  dst = string;
15946  length = &num_len;
15947  }
15948 
15949  edit.w = (float)size + 2 * style->padding.x;
15950  edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
15951  edit.x = right.x - (edit.w + style->padding.x);
15952  edit.y = property.y + style->border;
15953  edit.h = property.h - (2 * style->border);
15954 
15955  /* empty left space activator */
15956  empty.w = edit.x - (label.x + label.w);
15957  empty.x = label.x + label.w;
15958  empty.y = property.y;
15959  empty.h = property.h;
15960 
15961  /* update property */
15962  old = (*state == NK_PROPERTY_EDIT);
15963  nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
15964 
15965  /* draw property */
15966  if (style->draw_begin) style->draw_begin(out, style->userdata);
15967  nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
15968  if (style->draw_end) style->draw_end(out, style->userdata);
15969 
15970  /* execute right button */
15971  if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
15972  switch (variant->kind) {
15973  default: break;
15974  case NK_PROPERTY_INT:
15975  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
15976  case NK_PROPERTY_FLOAT:
15977  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
15978  case NK_PROPERTY_DOUBLE:
15979  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
15980  }
15981  }
15982 
15983  /* execute left button */
15984  if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
15985  switch (variant->kind) {
15986  default: break;
15987  case NK_PROPERTY_INT:
15988  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
15989  case NK_PROPERTY_FLOAT:
15990  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
15991  case NK_PROPERTY_DOUBLE:
15992  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
15993  }
15994  }
15995 
15996  if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
15997  /* property has been activated so setup buffer */
15998  NK_MEMCPY(buffer, dst, (nk_size)*length);
15999  *cursor = nk_utf_len(buffer, *length);
16000  *len = *length;
16001  length = len;
16002  dst = buffer;
16003  active = 0;
16004  } else active = (*state == NK_PROPERTY_EDIT);
16005 
16006  /* execute and run text edit field */
16007  nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
16008  text_edit->active = (unsigned char)active;
16009  text_edit->string.len = *length;
16010  text_edit->cursor = NK_CLAMP(0, *cursor, *length);
16011  text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
16012  text_edit->select_end = NK_CLAMP(0,*select_end, *length);
16013  text_edit->string.buffer.allocated = (nk_size)*length;
16015  text_edit->string.buffer.memory.ptr = dst;
16016  text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
16017  text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
16018  nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
16019  filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
16020 
16021  *length = text_edit->string.len;
16022  active = text_edit->active;
16023  *cursor = text_edit->cursor;
16024  *select_begin = text_edit->select_start;
16025  *select_end = text_edit->select_end;
16026 
16027  if (active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
16028  active = !active;
16029 
16030  if (old && !active) {
16031  /* property is now not active so convert edit text to value*/
16032  *state = NK_PROPERTY_DEFAULT;
16033  buffer[*len] = '\0';
16034  switch (variant->kind) {
16035  default: break;
16036  case NK_PROPERTY_INT:
16037  variant->value.i = nk_strtoi(buffer, 0);
16038  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
16039  break;
16040  case NK_PROPERTY_FLOAT:
16041  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16042  variant->value.f = nk_strtof(buffer, 0);
16043  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
16044  break;
16045  case NK_PROPERTY_DOUBLE:
16046  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16047  variant->value.d = nk_strtod(buffer, 0);
16048  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
16049  break;
16050  }
16051  }
16052 }
16053 /* ===============================================================
16054  *
16055  * COLOR PICKER
16056  *
16057  * ===============================================================*/
16058 NK_INTERN int
16059 nk_color_picker_behavior(nk_flags *state,
16060  const struct nk_rect *bounds, const struct nk_rect *matrix,
16061  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16062  struct nk_color *color, const struct nk_input *in)
16063 {
16064  float hsva[4];
16065  int value_changed = 0;
16066  int hsv_changed = 0;
16067 
16068  NK_ASSERT(state);
16069  NK_ASSERT(matrix);
16070  NK_ASSERT(hue_bar);
16071  NK_ASSERT(color);
16072 
16073  /* color matrix */
16074  nk_color_hsva_fv(hsva, *color);
16075  if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
16076  hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
16077  hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
16078  value_changed = hsv_changed = 1;
16079  }
16080 
16081  /* hue bar */
16082  if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
16083  hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
16084  value_changed = hsv_changed = 1;
16085  }
16086 
16087  /* alpha bar */
16088  if (alpha_bar) {
16089  if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
16090  hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
16091  value_changed = 1;
16092  }
16093  }
16094  nk_widget_state_reset(state);
16095  if (hsv_changed) {
16096  *color = nk_hsva_fv(hsva);
16097  *state = NK_WIDGET_STATE_ACTIVE;
16098  }
16099  if (value_changed) {
16100  color->a = (nk_byte)(hsva[3] * 255.0f);
16101  *state = NK_WIDGET_STATE_ACTIVE;
16102  }
16103 
16104  /* set color picker widget state */
16105  if (nk_input_is_mouse_hovering_rect(in, *bounds))
16106  *state = NK_WIDGET_STATE_HOVERED;
16107  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16108  *state |= NK_WIDGET_STATE_ENTERED;
16109  else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16110  *state |= NK_WIDGET_STATE_LEFT;
16111  return value_changed;
16112 }
16113 
16114 NK_INTERN void
16115 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
16116  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16117  struct nk_color color)
16118 {
16119  NK_STORAGE const struct nk_color black = {0,0,0,255};
16120  NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
16121  NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
16122 
16123  const float crosshair_size = 7.0f;
16124  struct nk_color temp;
16125  float hsva[4];
16126  float line_y;
16127  int i;
16128 
16129  NK_ASSERT(o);
16130  NK_ASSERT(matrix);
16131  NK_ASSERT(hue_bar);
16132 
16133  /* draw hue bar */
16134  nk_color_hsv_fv(hsva, color);
16135  for (i = 0; i < 6; ++i) {
16136  NK_GLOBAL const struct nk_color hue_colors[] = {
16137  {255, 0, 0, 255},
16138  {255,255,0,255},
16139  {0,255,0,255},
16140  {0, 255,255,255},
16141  {0,0,255,255},
16142  {255, 0, 255, 255},
16143  {255, 0, 0, 255}
16144  };
16146  nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
16147  hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
16148  hue_colors[i+1], hue_colors[i+1]);
16149  }
16150  line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
16151  nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
16152  line_y, 1, nk_rgb(255,255,255));
16153 
16154  /* draw alpha bar */
16155  if (alpha_bar) {
16156  float alpha = NK_SATURATE((float)color.a/255.0f);
16157  line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f);
16158 
16159  nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
16160  nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
16161  line_y, 1, nk_rgb(255,255,255));
16162  }
16163 
16164  /* draw color matrix */
16165  temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
16166  nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
16167  nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
16168 
16169  /* draw cross-hair */
16170  {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
16171  p.x = (float)(int)(matrix->x + S * matrix->w);
16172  p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
16173  nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
16174  nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
16175  nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
16176  nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
16177 }
16178 
16179 NK_INTERN int
16180 nk_do_color_picker(nk_flags *state,
16181  struct nk_command_buffer *out, struct nk_color *color,
16182  enum nk_color_format fmt, struct nk_rect bounds,
16183  struct nk_vec2 padding, const struct nk_input *in,
16184  const struct nk_user_font *font)
16185 {
16186  int ret = 0;
16187  struct nk_rect matrix;
16188  struct nk_rect hue_bar;
16189  struct nk_rect alpha_bar;
16190  float bar_w;
16191 
16192  NK_ASSERT(out);
16193  NK_ASSERT(color);
16194  NK_ASSERT(state);
16195  NK_ASSERT(font);
16196  if (!out || !color || !state || !font)
16197  return ret;
16198 
16199  bar_w = font->height;
16200  bounds.x += padding.x;
16201  bounds.y += padding.x;
16202  bounds.w -= 2 * padding.x;
16203  bounds.h -= 2 * padding.y;
16204 
16205  matrix.x = bounds.x;
16206  matrix.y = bounds.y;
16207  matrix.h = bounds.h;
16208  matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
16209 
16210  hue_bar.w = bar_w;
16211  hue_bar.y = bounds.y;
16212  hue_bar.h = matrix.h;
16213  hue_bar.x = matrix.x + matrix.w + padding.x;
16214 
16215  alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
16216  alpha_bar.y = bounds.y;
16217  alpha_bar.w = bar_w;
16218  alpha_bar.h = matrix.h;
16219 
16220  ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
16221  (fmt == NK_RGBA) ? &alpha_bar:0, color, in);
16222  nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *color);
16223  return ret;
16224 }
16225 
16226 /* ==============================================================
16227  *
16228  * STYLE
16229  *
16230  * ===============================================================*/
16231 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
16232 #define NK_COLOR_MAP(NK_COLOR)\
16233  NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \
16234  NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \
16235  NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \
16236  NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \
16237  NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \
16238  NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \
16239  NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \
16240  NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \
16241  NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \
16242  NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \
16243  NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \
16244  NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \
16245  NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \
16246  NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \
16247  NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \
16248  NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
16249  NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \
16250  NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \
16251  NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \
16252  NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \
16253  NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \
16254  NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \
16255  NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,255, 0, 0, 255) \
16256  NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \
16257  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \
16258  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,120,120,120,255) \
16259  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,150,150,150,255) \
16260  NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255)
16261 
16262 NK_GLOBAL const struct nk_color
16263 nk_default_color_style[NK_COLOR_COUNT] = {
16264 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
16265  NK_COLOR_MAP(NK_COLOR)
16266 #undef NK_COLOR
16267 };
16268 
16269 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
16270 #define NK_COLOR(a,b,c,d,e) #a,
16271  NK_COLOR_MAP(NK_COLOR)
16272 #undef NK_COLOR
16273 };
16274 
16276 {return nk_color_names[c];}
16277 
16279 {struct nk_style_item i; i.type = NK_STYLE_ITEM_IMAGE; i.data.image = img; return i;}
16280 
16282 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = col; return i;}
16283 
16285 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = nk_rgba(0,0,0,0); return i;}
16286 
16287 NK_API void
16288 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
16289 {
16290  struct nk_style *style;
16291  struct nk_style_text *text;
16292  struct nk_style_button *button;
16293  struct nk_style_toggle *toggle;
16294  struct nk_style_selectable *select;
16295  struct nk_style_slider *slider;
16296  struct nk_style_progress *prog;
16297  struct nk_style_scrollbar *scroll;
16298  struct nk_style_edit *edit;
16299  struct nk_style_property *property;
16300  struct nk_style_combo *combo;
16301  struct nk_style_chart *chart;
16302  struct nk_style_tab *tab;
16303  struct nk_style_window *win;
16304 
16305  NK_ASSERT(ctx);
16306  if (!ctx) return;
16307  style = &ctx->style;
16308  table = (!table) ? nk_default_color_style: table;
16309 
16310  /* default text */
16311  text = &style->text;
16312  text->color = table[NK_COLOR_TEXT];
16313  text->padding = nk_vec2(0,0);
16314 
16315  /* default button */
16316  button = &style->button;
16317  nk_zero_struct(*button);
16318  button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]);
16321  button->border_color = table[NK_COLOR_BORDER];
16322  button->text_background = table[NK_COLOR_BUTTON];
16323  button->text_normal = table[NK_COLOR_TEXT];
16324  button->text_hover = table[NK_COLOR_TEXT];
16325  button->text_active = table[NK_COLOR_TEXT];
16326  button->padding = nk_vec2(2.0f,2.0f);
16327  button->image_padding = nk_vec2(0.0f,0.0f);
16328  button->touch_padding = nk_vec2(0.0f, 0.0f);
16329  button->userdata = nk_handle_ptr(0);
16330  button->text_alignment = NK_TEXT_CENTERED;
16331  button->border = 1.0f;
16332  button->rounding = 4.0f;
16333  button->draw_begin = 0;
16334  button->draw_end = 0;
16335 
16336  /* contextual button */
16337  button = &style->contextual_button;
16338  nk_zero_struct(*button);
16339  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16342  button->border_color = table[NK_COLOR_WINDOW];
16343  button->text_background = table[NK_COLOR_WINDOW];
16344  button->text_normal = table[NK_COLOR_TEXT];
16345  button->text_hover = table[NK_COLOR_TEXT];
16346  button->text_active = table[NK_COLOR_TEXT];
16347  button->padding = nk_vec2(2.0f,2.0f);
16348  button->touch_padding = nk_vec2(0.0f,0.0f);
16349  button->userdata = nk_handle_ptr(0);
16350  button->text_alignment = NK_TEXT_CENTERED;
16351  button->border = 0.0f;
16352  button->rounding = 0.0f;
16353  button->draw_begin = 0;
16354  button->draw_end = 0;
16355 
16356  /* menu button */
16357  button = &style->menu_button;
16358  nk_zero_struct(*button);
16359  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16360  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
16361  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
16362  button->border_color = table[NK_COLOR_WINDOW];
16363  button->text_background = table[NK_COLOR_WINDOW];
16364  button->text_normal = table[NK_COLOR_TEXT];
16365  button->text_hover = table[NK_COLOR_TEXT];
16366  button->text_active = table[NK_COLOR_TEXT];
16367  button->padding = nk_vec2(2.0f,2.0f);
16368  button->touch_padding = nk_vec2(0.0f,0.0f);
16369  button->userdata = nk_handle_ptr(0);
16370  button->text_alignment = NK_TEXT_CENTERED;
16371  button->border = 0.0f;
16372  button->rounding = 1.0f;
16373  button->draw_begin = 0;
16374  button->draw_end = 0;
16375 
16376  /* checkbox toggle */
16377  toggle = &style->checkbox;
16378  nk_zero_struct(*toggle);
16379  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
16384  toggle->userdata = nk_handle_ptr(0);
16385  toggle->text_background = table[NK_COLOR_WINDOW];
16386  toggle->text_normal = table[NK_COLOR_TEXT];
16387  toggle->text_hover = table[NK_COLOR_TEXT];
16388  toggle->text_active = table[NK_COLOR_TEXT];
16389  toggle->padding = nk_vec2(2.0f, 2.0f);
16390  toggle->touch_padding = nk_vec2(0,0);
16391  toggle->border_color = nk_rgba(0,0,0,0);
16392  toggle->border = 0.0f;
16393  toggle->spacing = 4;
16394 
16395  /* option toggle */
16396  toggle = &style->option;
16397  nk_zero_struct(*toggle);
16398  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
16403  toggle->userdata = nk_handle_ptr(0);
16404  toggle->text_background = table[NK_COLOR_WINDOW];
16405  toggle->text_normal = table[NK_COLOR_TEXT];
16406  toggle->text_hover = table[NK_COLOR_TEXT];
16407  toggle->text_active = table[NK_COLOR_TEXT];
16408  toggle->padding = nk_vec2(3.0f, 3.0f);
16409  toggle->touch_padding = nk_vec2(0,0);
16410  toggle->border_color = nk_rgba(0,0,0,0);
16411  toggle->border = 0.0f;
16412  toggle->spacing = 4;
16413 
16414  /* selectable */
16415  select = &style->selectable;
16416  nk_zero_struct(*select);
16417  select->normal = nk_style_item_color(table[NK_COLOR_SELECT]);
16418  select->hover = nk_style_item_color(table[NK_COLOR_SELECT]);
16419  select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]);
16423  select->text_normal = table[NK_COLOR_TEXT];
16424  select->text_hover = table[NK_COLOR_TEXT];
16425  select->text_pressed = table[NK_COLOR_TEXT];
16426  select->text_normal_active = table[NK_COLOR_TEXT];
16427  select->text_hover_active = table[NK_COLOR_TEXT];
16428  select->text_pressed_active = table[NK_COLOR_TEXT];
16429  select->padding = nk_vec2(2.0f,2.0f);
16430  select->touch_padding = nk_vec2(0,0);
16431  select->userdata = nk_handle_ptr(0);
16432  select->rounding = 0.0f;
16433  select->draw_begin = 0;
16434  select->draw_end = 0;
16435 
16436  /* slider */
16437  slider = &style->slider;
16438  nk_zero_struct(*slider);
16439  slider->normal = nk_style_item_hide();
16440  slider->hover = nk_style_item_hide();
16441  slider->active = nk_style_item_hide();
16442  slider->bar_normal = table[NK_COLOR_SLIDER];
16443  slider->bar_hover = table[NK_COLOR_SLIDER];
16444  slider->bar_active = table[NK_COLOR_SLIDER];
16445  slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR];
16451  slider->cursor_size = nk_vec2(16,16);
16452  slider->padding = nk_vec2(2,2);
16453  slider->spacing = nk_vec2(2,2);
16454  slider->userdata = nk_handle_ptr(0);
16455  slider->show_buttons = nk_false;
16456  slider->bar_height = 8;
16457  slider->rounding = 0;
16458  slider->draw_begin = 0;
16459  slider->draw_end = 0;
16460 
16461  /* slider buttons */
16462  button = &style->slider.inc_button;
16463  button->normal = nk_style_item_color(nk_rgb(40,40,40));
16464  button->hover = nk_style_item_color(nk_rgb(42,42,42));
16465  button->active = nk_style_item_color(nk_rgb(44,44,44));
16466  button->border_color = nk_rgb(65,65,65);
16467  button->text_background = nk_rgb(40,40,40);
16468  button->text_normal = nk_rgb(175,175,175);
16469  button->text_hover = nk_rgb(175,175,175);
16470  button->text_active = nk_rgb(175,175,175);
16471  button->padding = nk_vec2(8.0f,8.0f);
16472  button->touch_padding = nk_vec2(0.0f,0.0f);
16473  button->userdata = nk_handle_ptr(0);
16474  button->text_alignment = NK_TEXT_CENTERED;
16475  button->border = 1.0f;
16476  button->rounding = 0.0f;
16477  button->draw_begin = 0;
16478  button->draw_end = 0;
16479  style->slider.dec_button = style->slider.inc_button;
16480 
16481  /* progressbar */
16482  prog = &style->progress;
16483  nk_zero_struct(*prog);
16484  prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]);
16485  prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]);
16486  prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]);
16490  prog->border_color = nk_rgba(0,0,0,0);
16491  prog->cursor_border_color = nk_rgba(0,0,0,0);
16492  prog->userdata = nk_handle_ptr(0);
16493  prog->padding = nk_vec2(4,4);
16494  prog->rounding = 0;
16495  prog->border = 0;
16496  prog->cursor_rounding = 0;
16497  prog->cursor_border = 0;
16498  prog->draw_begin = 0;
16499  prog->draw_end = 0;
16500 
16501  /* scrollbars */
16502  scroll = &style->scrollh;
16503  nk_zero_struct(*scroll);
16504  scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16505  scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16506  scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16512  scroll->userdata = nk_handle_ptr(0);
16513  scroll->border_color = table[NK_COLOR_SCROLLBAR];
16514  scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
16515  scroll->padding = nk_vec2(0,0);
16516  scroll->show_buttons = nk_false;
16517  scroll->border = 0;
16518  scroll->rounding = 0;
16519  scroll->border_cursor = 0;
16520  scroll->rounding_cursor = 0;
16521  scroll->draw_begin = 0;
16522  scroll->draw_end = 0;
16523  style->scrollv = style->scrollh;
16524 
16525  /* scrollbars buttons */
16526  button = &style->scrollh.inc_button;
16527  button->normal = nk_style_item_color(nk_rgb(40,40,40));
16528  button->hover = nk_style_item_color(nk_rgb(42,42,42));
16529  button->active = nk_style_item_color(nk_rgb(44,44,44));
16530  button->border_color = nk_rgb(65,65,65);
16531  button->text_background = nk_rgb(40,40,40);
16532  button->text_normal = nk_rgb(175,175,175);
16533  button->text_hover = nk_rgb(175,175,175);
16534  button->text_active = nk_rgb(175,175,175);
16535  button->padding = nk_vec2(4.0f,4.0f);
16536  button->touch_padding = nk_vec2(0.0f,0.0f);
16537  button->userdata = nk_handle_ptr(0);
16538  button->text_alignment = NK_TEXT_CENTERED;
16539  button->border = 1.0f;
16540  button->rounding = 0.0f;
16541  button->draw_begin = 0;
16542  button->draw_end = 0;
16543  style->scrollh.dec_button = style->scrollh.inc_button;
16544  style->scrollv.inc_button = style->scrollh.inc_button;
16545  style->scrollv.dec_button = style->scrollh.inc_button;
16546 
16547  /* edit */
16548  edit = &style->edit;
16549  nk_zero_struct(*edit);
16550  edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]);
16551  edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]);
16552  edit->active = nk_style_item_color(table[NK_COLOR_EDIT]);
16553  edit->cursor_normal = table[NK_COLOR_TEXT];
16554  edit->cursor_hover = table[NK_COLOR_TEXT];
16555  edit->cursor_text_normal= table[NK_COLOR_EDIT];
16556  edit->cursor_text_hover = table[NK_COLOR_EDIT];
16557  edit->border_color = table[NK_COLOR_BORDER];
16558  edit->text_normal = table[NK_COLOR_TEXT];
16559  edit->text_hover = table[NK_COLOR_TEXT];
16560  edit->text_active = table[NK_COLOR_TEXT];
16561  edit->selected_normal = table[NK_COLOR_TEXT];
16562  edit->selected_hover = table[NK_COLOR_TEXT];
16563  edit->selected_text_normal = table[NK_COLOR_EDIT];
16564  edit->selected_text_hover = table[NK_COLOR_EDIT];
16565  edit->scrollbar_size = nk_vec2(10,10);
16566  edit->scrollbar = style->scrollv;
16567  edit->padding = nk_vec2(4,4);
16568  edit->row_padding = 2;
16569  edit->cursor_size = 4;
16570  edit->border = 1;
16571  edit->rounding = 0;
16572 
16573  /* property */
16574  property = &style->property;
16575  nk_zero_struct(*property);
16576  property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16577  property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16578  property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16579  property->border_color = table[NK_COLOR_BORDER];
16580  property->label_normal = table[NK_COLOR_TEXT];
16581  property->label_hover = table[NK_COLOR_TEXT];
16582  property->label_active = table[NK_COLOR_TEXT];
16583  property->sym_left = NK_SYMBOL_TRIANGLE_LEFT;
16584  property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
16585  property->userdata = nk_handle_ptr(0);
16586  property->padding = nk_vec2(4,4);
16587  property->border = 1;
16588  property->rounding = 10;
16589  property->draw_begin = 0;
16590  property->draw_end = 0;
16591 
16592  /* property buttons */
16593  button = &style->property.dec_button;
16594  nk_zero_struct(*button);
16595  button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16596  button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16597  button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16598  button->border_color = nk_rgba(0,0,0,0);
16599  button->text_background = table[NK_COLOR_PROPERTY];
16600  button->text_normal = table[NK_COLOR_TEXT];
16601  button->text_hover = table[NK_COLOR_TEXT];
16602  button->text_active = table[NK_COLOR_TEXT];
16603  button->padding = nk_vec2(0.0f,0.0f);
16604  button->touch_padding = nk_vec2(0.0f,0.0f);
16605  button->userdata = nk_handle_ptr(0);
16606  button->text_alignment = NK_TEXT_CENTERED;
16607  button->border = 0.0f;
16608  button->rounding = 0.0f;
16609  button->draw_begin = 0;
16610  button->draw_end = 0;
16611  style->property.inc_button = style->property.dec_button;
16612 
16613  /* property edit */
16614  edit = &style->property.edit;
16615  nk_zero_struct(*edit);
16619  edit->border_color = nk_rgba(0,0,0,0);
16620  edit->cursor_normal = table[NK_COLOR_TEXT];
16621  edit->cursor_hover = table[NK_COLOR_TEXT];
16622  edit->cursor_text_normal= table[NK_COLOR_EDIT];
16623  edit->cursor_text_hover = table[NK_COLOR_EDIT];
16624  edit->text_normal = table[NK_COLOR_TEXT];
16625  edit->text_hover = table[NK_COLOR_TEXT];
16626  edit->text_active = table[NK_COLOR_TEXT];
16627  edit->selected_normal = table[NK_COLOR_TEXT];
16628  edit->selected_hover = table[NK_COLOR_TEXT];
16629  edit->selected_text_normal = table[NK_COLOR_EDIT];
16630  edit->selected_text_hover = table[NK_COLOR_EDIT];
16631  edit->padding = nk_vec2(0,0);
16632  edit->cursor_size = 8;
16633  edit->border = 0;
16634  edit->rounding = 0;
16635 
16636  /* chart */
16637  chart = &style->chart;
16638  nk_zero_struct(*chart);
16640  chart->border_color = table[NK_COLOR_BORDER];
16642  chart->color = table[NK_COLOR_CHART_COLOR];
16643  chart->padding = nk_vec2(4,4);
16644  chart->border = 0;
16645  chart->rounding = 0;
16646 
16647  /* combo */
16648  combo = &style->combo;
16649  combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
16650  combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
16651  combo->active = nk_style_item_color(table[NK_COLOR_COMBO]);
16652  combo->border_color = table[NK_COLOR_BORDER];
16653  combo->label_normal = table[NK_COLOR_TEXT];
16654  combo->label_hover = table[NK_COLOR_TEXT];
16655  combo->label_active = table[NK_COLOR_TEXT];
16659  combo->content_padding = nk_vec2(4,4);
16660  combo->button_padding = nk_vec2(0,4);
16661  combo->spacing = nk_vec2(4,0);
16662  combo->border = 1;
16663  combo->rounding = 0;
16664 
16665  /* combo button */
16666  button = &style->combo.button;
16667  nk_zero_struct(*button);
16668  button->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
16669  button->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
16670  button->active = nk_style_item_color(table[NK_COLOR_COMBO]);
16671  button->border_color = nk_rgba(0,0,0,0);
16672  button->text_background = table[NK_COLOR_COMBO];
16673  button->text_normal = table[NK_COLOR_TEXT];
16674  button->text_hover = table[NK_COLOR_TEXT];
16675  button->text_active = table[NK_COLOR_TEXT];
16676  button->padding = nk_vec2(2.0f,2.0f);
16677  button->touch_padding = nk_vec2(0.0f,0.0f);
16678  button->userdata = nk_handle_ptr(0);
16679  button->text_alignment = NK_TEXT_CENTERED;
16680  button->border = 0.0f;
16681  button->rounding = 0.0f;
16682  button->draw_begin = 0;
16683  button->draw_end = 0;
16684 
16685  /* tab */
16686  tab = &style->tab;
16688  tab->border_color = table[NK_COLOR_BORDER];
16689  tab->text = table[NK_COLOR_TEXT];
16692  tab->padding = nk_vec2(4,4);
16693  tab->spacing = nk_vec2(4,4);
16694  tab->indent = 10.0f;
16695  tab->border = 1;
16696  tab->rounding = 0;
16697 
16698  /* tab button */
16699  button = &style->tab.tab_minimize_button;
16700  nk_zero_struct(*button);
16702  button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
16704  button->border_color = nk_rgba(0,0,0,0);
16705  button->text_background = table[NK_COLOR_TAB_HEADER];
16706  button->text_normal = table[NK_COLOR_TEXT];
16707  button->text_hover = table[NK_COLOR_TEXT];
16708  button->text_active = table[NK_COLOR_TEXT];
16709  button->padding = nk_vec2(2.0f,2.0f);
16710  button->touch_padding = nk_vec2(0.0f,0.0f);
16711  button->userdata = nk_handle_ptr(0);
16712  button->text_alignment = NK_TEXT_CENTERED;
16713  button->border = 0.0f;
16714  button->rounding = 0.0f;
16715  button->draw_begin = 0;
16716  button->draw_end = 0;
16717  style->tab.tab_maximize_button =*button;
16718 
16719  /* node button */
16720  button = &style->tab.node_minimize_button;
16721  nk_zero_struct(*button);
16722  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16723  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
16724  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
16725  button->border_color = nk_rgba(0,0,0,0);
16726  button->text_background = table[NK_COLOR_TAB_HEADER];
16727  button->text_normal = table[NK_COLOR_TEXT];
16728  button->text_hover = table[NK_COLOR_TEXT];
16729  button->text_active = table[NK_COLOR_TEXT];
16730  button->padding = nk_vec2(2.0f,2.0f);
16731  button->touch_padding = nk_vec2(0.0f,0.0f);
16732  button->userdata = nk_handle_ptr(0);
16733  button->text_alignment = NK_TEXT_CENTERED;
16734  button->border = 0.0f;
16735  button->rounding = 0.0f;
16736  button->draw_begin = 0;
16737  button->draw_end = 0;
16738  style->tab.node_maximize_button =*button;
16739 
16740  /* window header */
16741  win = &style->window;
16742  win->header.align = NK_HEADER_RIGHT;
16749  win->header.label_normal = table[NK_COLOR_TEXT];
16750  win->header.label_hover = table[NK_COLOR_TEXT];
16751  win->header.label_active = table[NK_COLOR_TEXT];
16752  win->header.label_padding = nk_vec2(4,4);
16753  win->header.padding = nk_vec2(4,4);
16754  win->header.spacing = nk_vec2(0,0);
16755 
16756  /* window header close button */
16757  button = &style->window.header.close_button;
16758  nk_zero_struct(*button);
16759  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
16760  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
16761  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
16762  button->border_color = nk_rgba(0,0,0,0);
16763  button->text_background = table[NK_COLOR_HEADER];
16764  button->text_normal = table[NK_COLOR_TEXT];
16765  button->text_hover = table[NK_COLOR_TEXT];
16766  button->text_active = table[NK_COLOR_TEXT];
16767  button->padding = nk_vec2(0.0f,0.0f);
16768  button->touch_padding = nk_vec2(0.0f,0.0f);
16769  button->userdata = nk_handle_ptr(0);
16770  button->text_alignment = NK_TEXT_CENTERED;
16771  button->border = 0.0f;
16772  button->rounding = 0.0f;
16773  button->draw_begin = 0;
16774  button->draw_end = 0;
16775 
16776  /* window header minimize button */
16777  button = &style->window.header.minimize_button;
16778  nk_zero_struct(*button);
16779  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
16780  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
16781  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
16782  button->border_color = nk_rgba(0,0,0,0);
16783  button->text_background = table[NK_COLOR_HEADER];
16784  button->text_normal = table[NK_COLOR_TEXT];
16785  button->text_hover = table[NK_COLOR_TEXT];
16786  button->text_active = table[NK_COLOR_TEXT];
16787  button->padding = nk_vec2(0.0f,0.0f);
16788  button->touch_padding = nk_vec2(0.0f,0.0f);
16789  button->userdata = nk_handle_ptr(0);
16790  button->text_alignment = NK_TEXT_CENTERED;
16791  button->border = 0.0f;
16792  button->rounding = 0.0f;
16793  button->draw_begin = 0;
16794  button->draw_end = 0;
16795 
16796  /* window */
16797  win->background = table[NK_COLOR_WINDOW];
16799  win->border_color = table[NK_COLOR_BORDER];
16800  win->popup_border_color = table[NK_COLOR_BORDER];
16801  win->combo_border_color = table[NK_COLOR_BORDER];
16803  win->menu_border_color = table[NK_COLOR_BORDER];
16804  win->group_border_color = table[NK_COLOR_BORDER];
16805  win->tooltip_border_color = table[NK_COLOR_BORDER];
16806  win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
16807 
16808  win->rounding = 0.0f;
16809  win->spacing = nk_vec2(4,4);
16810  win->scrollbar_size = nk_vec2(10,10);
16811  win->min_size = nk_vec2(64,64);
16812 
16813  win->combo_border = 1.0f;
16814  win->contextual_border = 1.0f;
16815  win->menu_border = 1.0f;
16816  win->group_border = 1.0f;
16817  win->tooltip_border = 1.0f;
16818  win->popup_border = 1.0f;
16819  win->border = 2.0f;
16820 
16821  win->padding = nk_vec2(4,4);
16822  win->group_padding = nk_vec2(4,4);
16823  win->popup_padding = nk_vec2(4,4);
16824  win->combo_padding = nk_vec2(4,4);
16825  win->contextual_padding = nk_vec2(4,4);
16826  win->menu_padding = nk_vec2(4,4);
16827  win->tooltip_padding = nk_vec2(4,4);
16828 }
16829 
16830 NK_API void
16831 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
16832 {
16833  struct nk_style *style;
16834  NK_ASSERT(ctx);
16835  if (!ctx) return;
16836  style = &ctx->style;
16837  style->font = font;
16838  ctx->stacks.fonts.head = 0;
16839 }
16840 
16841 NK_API int
16842 nk_style_push_font(struct nk_context *ctx, struct nk_user_font *font)
16843 {
16844  struct nk_config_stack_user_font *font_stack;
16845  struct nk_config_stack_user_font_element *element;
16846 
16847  NK_ASSERT(ctx);
16848  if (!ctx) return 0;
16849 
16850  font_stack = &ctx->stacks.fonts;
16851  NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
16852  if (font_stack->head >= (int)NK_LEN(font_stack->elements))
16853  return 0;
16854 
16855  element = &font_stack->elements[font_stack->head++];
16856  element->address = &ctx->style.font;
16857  element->old_value = ctx->style.font;
16858  ctx->style.font = font;
16859  return 1;
16860 }
16861 
16862 NK_API int
16863 nk_style_pop_font(struct nk_context *ctx)
16864 {
16865  struct nk_config_stack_user_font *font_stack;
16866  struct nk_config_stack_user_font_element *element;
16867 
16868  NK_ASSERT(ctx);
16869  if (!ctx) return 0;
16870 
16871  font_stack = &ctx->stacks.fonts;
16872  NK_ASSERT(font_stack->head > 0);
16873  if (font_stack->head < 1)
16874  return 0;
16875 
16876  element = &font_stack->elements[--font_stack->head];
16877  *element->address = element->old_value;
16878  return 1;
16879 }
16880 
16881 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
16882 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
16883 {\
16884  struct nk_config_stack_##type * type_stack;\
16885  struct nk_config_stack_##type##_element *element;\
16886  NK_ASSERT(ctx);\
16887  if (!ctx) return 0;\
16888  type_stack = &ctx->stacks.stack;\
16889  NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
16890  if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
16891  return 0;\
16892  element = &type_stack->elements[type_stack->head++];\
16893  element->address = address;\
16894  element->old_value = *address;\
16895  *address = value;\
16896  return 1;\
16897 }
16898 
16899 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
16900 nk_style_pop_##type(struct nk_context *ctx)\
16901 {\
16902  struct nk_config_stack_##type *type_stack;\
16903  struct nk_config_stack_##type##_element *element;\
16904  NK_ASSERT(ctx);\
16905  if (!ctx) return 0;\
16906  type_stack = &ctx->stacks.stack;\
16907  NK_ASSERT(type_stack->head > 0);\
16908  if (type_stack->head < 1)\
16909  return 0;\
16910  element = &type_stack->elements[--type_stack->head];\
16911  *element->address = element->old_value;\
16912  return 1;\
16913 }
16914 
16915 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
16916 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
16917 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
16918 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
16919 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
16920 
16921 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
16922 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
16923 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
16924 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
16925 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
16926 
16927 NK_API int
16928 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
16929 {
16930  struct nk_style *style;
16931  NK_ASSERT(ctx);
16932  if (!ctx) return 0;
16933  style = &ctx->style;
16934  if (style->cursors[c]) {
16935  style->cursor_active = style->cursors[c];
16936  return 1;
16937  }
16938  return 0;
16939 }
16940 
16941 NK_API void
16942 nk_style_show_cursor(struct nk_context *ctx)
16943 {
16944  ctx->style.cursor_visible = nk_true;
16945 }
16946 
16947 NK_API void
16948 nk_style_hide_cursor(struct nk_context *ctx)
16949 {
16950  ctx->style.cursor_visible = nk_false;
16951 }
16952 
16953 NK_API void
16954 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
16955  const struct nk_cursor *c)
16956 {
16957  struct nk_style *style;
16958  NK_ASSERT(ctx);
16959  if (!ctx) return;
16960  style = &ctx->style;
16961  style->cursors[cursor] = c;
16962 }
16963 
16964 NK_API void
16965 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors)
16966 {
16967  int i = 0;
16968  struct nk_style *style;
16969  NK_ASSERT(ctx);
16970  if (!ctx) return;
16971  style = &ctx->style;
16972  for (i = 0; i < NK_CURSOR_COUNT; ++i)
16973  style->cursors[i] = &cursors[i];
16974  style->cursor_visible = nk_true;
16975 }
16976 
16977 /* ===============================================================
16978  *
16979  * POOL
16980  *
16981  * ===============================================================*/
16982 NK_INTERN void
16983 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
16984  unsigned int capacity)
16985 {
16986  nk_zero(pool, sizeof(*pool));
16987  pool->alloc = *alloc;
16988  pool->capacity = capacity;
16989  pool->type = NK_BUFFER_DYNAMIC;
16990  pool->pages = 0;
16991 }
16992 
16993 NK_INTERN void
16994 nk_pool_free(struct nk_pool *pool)
16995 {
16996  struct nk_page *iter = pool->pages;
16997  if (!pool) return;
16998  if (pool->type == NK_BUFFER_FIXED) return;
16999  while (iter) {
17000  struct nk_page *next = iter->next;
17001  pool->alloc.free(pool->alloc.userdata, iter);
17002  iter = next;
17003  }
17004 }
17005 
17006 NK_INTERN void
17007 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
17008 {
17009  nk_zero(pool, sizeof(*pool));
17010  NK_ASSERT(size >= sizeof(struct nk_page));
17011  if (size < sizeof(struct nk_page)) return;
17012  pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
17013  pool->pages = (struct nk_page*)memory;
17014  pool->type = NK_BUFFER_FIXED;
17015  pool->size = size;
17016 }
17017 
17018 NK_INTERN struct nk_page_element*
17019 nk_pool_alloc(struct nk_pool *pool)
17020 {
17021  if (!pool->pages || pool->pages->size >= pool->capacity) {
17022  /* allocate new page */
17023  struct nk_page *page;
17024  if (pool->type == NK_BUFFER_FIXED) {
17025  if (!pool->pages) {
17026  NK_ASSERT(pool->pages);
17027  return 0;
17028  }
17029  NK_ASSERT(pool->pages->size < pool->capacity);
17030  return 0;
17031  } else {
17032  nk_size size = sizeof(struct nk_page);
17033  size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
17034  page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
17035  page->next = pool->pages;
17036  pool->pages = page;
17037  page->size = 0;
17038  }
17039  }
17040  return &pool->pages->win[pool->pages->size++];
17041 }
17042 
17043 /* ===============================================================
17044  *
17045  * CONTEXT
17046  *
17047  * ===============================================================*/
17048 NK_INTERN void* nk_create_window(struct nk_context *ctx);
17049 NK_INTERN void nk_remove_window(struct nk_context*, struct nk_window*);
17050 NK_INTERN void nk_free_window(struct nk_context *ctx, struct nk_window *win);
17051 NK_INTERN void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
17052 NK_INTERN void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
17053 NK_INTERN void* nk_create_panel(struct nk_context *ctx);
17054 NK_INTERN void nk_free_panel(struct nk_context*, struct nk_panel *pan);
17055 
17056 NK_INTERN void
17057 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
17058 {
17059  NK_ASSERT(ctx);
17060  if (!ctx) return;
17061  nk_zero_struct(*ctx);
17062  nk_style_default(ctx);
17063  ctx->seq = 1;
17064  if (font) ctx->style.font = font;
17065 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17066  nk_draw_list_init(&ctx->draw_list);
17067 #endif
17068 }
17069 
17070 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
17071 NK_API int
17072 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
17073 {
17074  struct nk_allocator alloc;
17075  alloc.userdata.ptr = 0;
17076  alloc.alloc = nk_malloc;
17077  alloc.free = nk_mfree;
17078  return nk_init(ctx, &alloc, font);
17079 }
17080 #endif
17081 
17082 NK_API int
17083 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
17084  const struct nk_user_font *font)
17085 {
17086  NK_ASSERT(memory);
17087  if (!memory) return 0;
17088  nk_setup(ctx, font);
17089  nk_buffer_init_fixed(&ctx->memory, memory, size);
17090  ctx->use_pool = nk_false;
17091  return 1;
17092 }
17093 
17094 NK_API int
17095 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
17096  struct nk_buffer *pool, const struct nk_user_font *font)
17097 {
17098  NK_ASSERT(cmds);
17099  NK_ASSERT(pool);
17100  if (!cmds || !pool) return 0;
17101 
17102  nk_setup(ctx, font);
17103  ctx->memory = *cmds;
17104  if (pool->type == NK_BUFFER_FIXED) {
17105  /* take memory from buffer and alloc fixed pool */
17106  nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
17107  } else {
17108  /* create dynamic pool from buffer allocator */
17109  struct nk_allocator *alloc = &pool->pool;
17110  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17111  }
17112  ctx->use_pool = nk_true;
17113  return 1;
17114 }
17115 
17116 NK_API int
17117 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
17118  const struct nk_user_font *font)
17119 {
17120  NK_ASSERT(alloc);
17121  if (!alloc) return 0;
17122  nk_setup(ctx, font);
17123  nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
17124  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17125  ctx->use_pool = nk_true;
17126  return 1;
17127 }
17128 
17129 #ifdef NK_INCLUDE_COMMAND_USERDATA
17130 NK_API void
17131 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
17132 {
17133  if (!ctx) return;
17134  ctx->userdata = handle;
17135  if (ctx->current)
17136  ctx->current->buffer.userdata = handle;
17137 }
17138 #endif
17139 
17140 NK_API void
17141 nk_free(struct nk_context *ctx)
17142 {
17143  NK_ASSERT(ctx);
17144  if (!ctx) return;
17145  nk_buffer_free(&ctx->memory);
17146  if (ctx->use_pool)
17147  nk_pool_free(&ctx->pool);
17148 
17149  nk_zero(&ctx->input, sizeof(ctx->input));
17150  nk_zero(&ctx->style, sizeof(ctx->style));
17151  nk_zero(&ctx->memory, sizeof(ctx->memory));
17152 
17153  ctx->seq = 0;
17154  ctx->build = 0;
17155  ctx->begin = 0;
17156  ctx->end = 0;
17157  ctx->active = 0;
17158  ctx->current = 0;
17159  ctx->freelist = 0;
17160  ctx->count = 0;
17161 }
17162 
17163 NK_API void
17164 nk_clear(struct nk_context *ctx)
17165 {
17166  struct nk_window *iter;
17167  struct nk_window *next;
17168  NK_ASSERT(ctx);
17169 
17170  if (!ctx) return;
17171  if (ctx->use_pool)
17172  nk_buffer_clear(&ctx->memory);
17173  else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
17174 
17175  ctx->build = 0;
17176  ctx->memory.calls = 0;
17177  ctx->last_widget_state = 0;
17179  NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
17180 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17181  nk_draw_list_clear(&ctx->draw_list);
17182 #endif
17183 
17184  /* garbage collector */
17185  iter = ctx->begin;
17186  while (iter) {
17187  /* make sure minimized windows do not get removed */
17188  if ((iter->flags & NK_WINDOW_MINIMIZED) &&
17189  !(iter->flags & NK_WINDOW_CLOSED)) {
17190  iter = iter->next;
17191  continue;
17192  }
17193 
17194  /* remove hotness from hidden or closed windows*/
17195  if (((iter->flags & NK_WINDOW_HIDDEN) ||
17196  (iter->flags & NK_WINDOW_CLOSED)) &&
17197  iter == ctx->active)
17198  ctx->active = iter->next;
17199 
17200  /* free unused popup windows */
17201  if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
17202  nk_free_window(ctx, iter->popup.win);
17203  iter->popup.win = 0;
17204  }
17205 
17206  /* remove unused window state tables */
17207  {struct nk_table *n, *it = iter->tables;
17208  while (it) {
17209  n = it->next;
17210  if (it->seq != ctx->seq) {
17211  nk_remove_table(iter, it);
17212  nk_zero(it, sizeof(union nk_page_data));
17213  nk_free_table(ctx, it);
17214  if (it == iter->tables)
17215  iter->tables = n;
17216  }
17217  it = n;
17218  }}
17219 
17220  /* window itself is not used anymore so free */
17221  if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
17222  next = iter->next;
17223  nk_remove_window(ctx, iter);
17224  nk_free_window(ctx, iter);
17225  iter = next;
17226  } else iter = iter->next;
17227  }
17228  ctx->seq++;
17229 }
17230 
17231 /* ----------------------------------------------------------------
17232  *
17233  * BUFFERING
17234  *
17235  * ---------------------------------------------------------------*/
17236 NK_INTERN void
17237 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17238 {
17239  NK_ASSERT(ctx);
17240  NK_ASSERT(buffer);
17241  if (!ctx || !buffer) return;
17242  buffer->begin = ctx->memory.allocated;
17243  buffer->end = buffer->begin;
17244  buffer->last = buffer->begin;
17245  buffer->clip = nk_null_rect;
17246 }
17247 
17248 NK_INTERN void
17249 nk_start(struct nk_context *ctx, struct nk_window *win)
17250 {
17251  NK_ASSERT(ctx);
17252  NK_ASSERT(win);
17253  nk_start_buffer(ctx, &win->buffer);
17254 }
17255 
17256 NK_INTERN void
17257 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
17258 {
17259  struct nk_popup_buffer *buf;
17260  NK_ASSERT(ctx);
17261  NK_ASSERT(win);
17262  if (!ctx || !win) return;
17263 
17264  /* save buffer fill state for popup */
17265  buf = &win->popup.buf;
17266  buf->begin = win->buffer.end;
17267  buf->end = win->buffer.end;
17268  buf->parent = win->buffer.last;
17269  buf->last = buf->begin;
17270  buf->active = nk_true;
17271 }
17272 
17273 NK_INTERN void
17274 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
17275 {
17276  struct nk_popup_buffer *buf;
17277  NK_ASSERT(ctx);
17278  NK_ASSERT(win);
17279  if (!ctx || !win) return;
17280 
17281  buf = &win->popup.buf;
17282  buf->last = win->buffer.last;
17283  buf->end = win->buffer.end;
17284 }
17285 
17286 NK_INTERN void
17287 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17288 {
17289  NK_ASSERT(ctx);
17290  NK_ASSERT(buffer);
17291  if (!ctx || !buffer) return;
17292  buffer->end = ctx->memory.allocated;
17293 }
17294 
17295 NK_INTERN void
17296 nk_finish(struct nk_context *ctx, struct nk_window *win)
17297 {
17298  struct nk_popup_buffer *buf;
17299  struct nk_command *parent_last;
17300  void *memory;
17301 
17302  NK_ASSERT(ctx);
17303  NK_ASSERT(win);
17304  if (!ctx || !win) return;
17305  nk_finish_buffer(ctx, &win->buffer);
17306  if (!win->popup.buf.active) return;
17307 
17308  buf = &win->popup.buf;
17309  memory = ctx->memory.memory.ptr;
17310  parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
17311  parent_last->next = buf->end;
17312 }
17313 
17314 NK_INTERN void
17315 nk_build(struct nk_context *ctx)
17316 {
17317  struct nk_window *iter = 0;
17318  struct nk_command *cmd = 0;
17319  nk_byte *buffer = 0;
17320 
17321  /* draw cursor overlay */
17322  if (!ctx->style.cursor_active)
17324  if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
17325  struct nk_rect mouse_bounds;
17326  const struct nk_cursor *cursor = ctx->style.cursor_active;
17327  nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
17328  nk_start_buffer(ctx, &ctx->overlay);
17329 
17330  mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
17331  mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
17332  mouse_bounds.w = cursor->size.x;
17333  mouse_bounds.h = cursor->size.y;
17334 
17335  nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
17336  nk_finish_buffer(ctx, &ctx->overlay);
17337  }
17338  /* build one big draw command list out of all window buffers */
17339  iter = ctx->begin;
17340  buffer = (nk_byte*)ctx->memory.memory.ptr;
17341  while (iter != 0) {
17342  struct nk_window *next = iter->next;
17343  if (iter->buffer.last == iter->buffer.begin || (iter->flags & NK_WINDOW_HIDDEN))
17344  goto cont;
17345 
17346  cmd = nk_ptr_add(struct nk_command, buffer, iter->buffer.last);
17347  while (next && ((next->buffer.last == next->buffer.begin) ||
17348  (next->flags & NK_WINDOW_HIDDEN)))
17349  next = next->next; /* skip empty command buffers */
17350 
17351  if (next) cmd->next = next->buffer.begin;
17352  cont: iter = next;
17353  }
17354  /* append all popup draw commands into lists */
17355  iter = ctx->begin;
17356  while (iter != 0) {
17357  struct nk_window *next = iter->next;
17358  struct nk_popup_buffer *buf;
17359  if (!iter->popup.buf.active)
17360  goto skip;
17361 
17362  buf = &iter->popup.buf;
17363  cmd->next = buf->begin;
17364  cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
17365  buf->active = nk_false;
17366  skip: iter = next;
17367  }
17368  /* append overlay commands */
17369  if (cmd) {
17370  if (ctx->overlay.end != ctx->overlay.begin)
17371  cmd->next = ctx->overlay.begin;
17372  else cmd->next = ctx->memory.allocated;
17373  }
17374 }
17375 
17376 NK_API const struct nk_command*
17377 nk__begin(struct nk_context *ctx)
17378 {
17379  struct nk_window *iter;
17380  nk_byte *buffer;
17381  NK_ASSERT(ctx);
17382  if (!ctx) return 0;
17383  if (!ctx->count) return 0;
17384 
17385  buffer = (nk_byte*)ctx->memory.memory.ptr;
17386  if (!ctx->build) {
17387  nk_build(ctx);
17388  ctx->build = nk_true;
17389  }
17390 
17391  iter = ctx->begin;
17392  while (iter && ((iter->buffer.begin == iter->buffer.end) || (iter->flags & NK_WINDOW_HIDDEN)))
17393  iter = iter->next;
17394  if (!iter) return 0;
17395  return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
17396 }
17397 
17398 NK_API const struct nk_command*
17399 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
17400 {
17401  nk_byte *buffer;
17402  const struct nk_command *next;
17403  NK_ASSERT(ctx);
17404  if (!ctx || !cmd || !ctx->count) return 0;
17405  if (cmd->next >= ctx->memory.allocated) return 0;
17406  buffer = (nk_byte*)ctx->memory.memory.ptr;
17407  next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
17408  return next;
17409 }
17410 
17411 /* ----------------------------------------------------------------
17412  *
17413  * PANEL
17414  *
17415  * ---------------------------------------------------------------*/
17416 static int
17417 nk_panel_has_header(nk_flags flags, const char *title)
17418 {
17419  int active = 0;
17420  active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
17421  active = active || (flags & NK_WINDOW_TITLE);
17422  active = active && !(flags & NK_WINDOW_HIDDEN) && title;
17423  return active;
17424 }
17425 
17426 NK_INTERN struct nk_vec2
17427 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
17428 {
17429  switch (type) {
17430  default:
17431  case NK_PANEL_WINDOW: return style->window.padding;
17432  case NK_PANEL_GROUP: return style->window.group_padding;
17433  case NK_PANEL_POPUP: return style->window.popup_padding;
17434  case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
17435  case NK_PANEL_COMBO: return style->window.combo_padding;
17436  case NK_PANEL_MENU: return style->window.menu_padding;
17437  case NK_PANEL_TOOLTIP: return style->window.menu_padding;
17438  }
17439 }
17440 
17441 NK_INTERN float
17442 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
17443  enum nk_panel_type type)
17444 {
17445  if (flags & NK_WINDOW_BORDER) {
17446  switch (type) {
17447  default:
17448  case NK_PANEL_WINDOW: return style->window.border;
17449  case NK_PANEL_GROUP: return style->window.group_border;
17450  case NK_PANEL_POPUP: return style->window.popup_border;
17451  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
17452  case NK_PANEL_COMBO: return style->window.combo_border;
17453  case NK_PANEL_MENU: return style->window.menu_border;
17454  case NK_PANEL_TOOLTIP: return style->window.menu_border;
17455  }} else return 0;
17456 }
17457 
17458 NK_INTERN struct nk_color
17459 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
17460 {
17461  switch (type) {
17462  default:
17463  case NK_PANEL_WINDOW: return style->window.border_color;
17464  case NK_PANEL_GROUP: return style->window.group_border_color;
17465  case NK_PANEL_POPUP: return style->window.popup_border_color;
17466  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
17467  case NK_PANEL_COMBO: return style->window.combo_border_color;
17468  case NK_PANEL_MENU: return style->window.menu_border_color;
17469  case NK_PANEL_TOOLTIP: return style->window.menu_border_color;
17470  }
17471 }
17472 
17473 NK_INTERN int
17474 nk_panel_is_sub(enum nk_panel_type type)
17475 {
17476  return (type & NK_PANEL_SET_SUB)?1:0;
17477 }
17478 
17479 NK_INTERN int
17480 nk_panel_is_nonblock(enum nk_panel_type type)
17481 {
17482  return (type & NK_PANEL_SET_NONBLOCK)?1:0;
17483 }
17484 
17485 NK_INTERN int
17486 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
17487 {
17488  struct nk_input *in;
17489  struct nk_window *win;
17490  struct nk_panel *layout;
17491  struct nk_command_buffer *out;
17492  const struct nk_style *style;
17493  const struct nk_user_font *font;
17494 
17495  struct nk_vec2 scrollbar_size;
17496  struct nk_vec2 panel_padding;
17497 
17498  NK_ASSERT(ctx);
17499  NK_ASSERT(ctx->current);
17500  NK_ASSERT(ctx->current->layout);
17501  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
17502  nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
17503  if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
17504  nk_zero(ctx->current->layout, sizeof(struct nk_panel));
17505  ctx->current->layout->type = panel_type;
17506  return 0;
17507  }
17508  /* pull state into local stack */
17509  style = &ctx->style;
17510  font = style->font;
17511  win = ctx->current;
17512  layout = win->layout;
17513  out = &win->buffer;
17514  in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
17515 #ifdef NK_INCLUDE_COMMAND_USERDATA
17516  win->buffer.userdata = ctx->userdata;
17517 #endif
17518  /* pull style configuration into local stack */
17519  scrollbar_size = style->window.scrollbar_size;
17520  panel_padding = nk_panel_get_padding(style, panel_type);
17521 
17522  /* window movement */
17523  if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
17524  int left_mouse_down;
17525  int left_mouse_click_in_cursor;
17526 
17527  /* calculate draggable window space */
17528  struct nk_rect header;
17529  header.x = win->bounds.x;
17530  header.y = win->bounds.y;
17531  header.w = win->bounds.w;
17532  if (nk_panel_has_header(win->flags, title)) {
17533  header.h = font->height + 2.0f * style->window.header.padding.y;
17534  header.h += 2.0f * style->window.header.label_padding.y;
17535  } else header.h = panel_padding.y;
17536 
17537  /* window movement by dragging */
17538  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
17539  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
17540  NK_BUTTON_LEFT, header, nk_true);
17541  if (left_mouse_down && left_mouse_click_in_cursor) {
17542  win->bounds.x = win->bounds.x + in->mouse.delta.x;
17543  win->bounds.y = win->bounds.y + in->mouse.delta.y;
17547  }
17548  }
17549 
17550  /* setup panel */
17551  layout->type = panel_type;
17552  layout->flags = win->flags;
17553  layout->bounds = win->bounds;
17554  layout->bounds.x += panel_padding.x;
17555  layout->bounds.w -= 2*panel_padding.x;
17556  if (win->flags & NK_WINDOW_BORDER) {
17557  layout->border = nk_panel_get_border(style, win->flags, panel_type);
17558  layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
17559  } else layout->border = 0;
17560  layout->at_y = layout->bounds.y;
17561  layout->at_x = layout->bounds.x;
17562  layout->max_x = 0;
17563  layout->header_height = 0;
17564  layout->footer_height = 0;
17565  layout->row.index = 0;
17566  layout->row.columns = 0;
17567  layout->row.ratio = 0;
17568  layout->row.item_width = 0;
17569  layout->row.tree_depth = 0;
17570  layout->row.height = panel_padding.y;
17571  layout->has_scrolling = nk_true;
17572  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
17573  layout->bounds.w -= scrollbar_size.x;
17574  if (!nk_panel_is_nonblock(panel_type)) {
17575  layout->footer_height = 0;
17576  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
17577  layout->footer_height = scrollbar_size.y;
17578  layout->bounds.h -= layout->footer_height;
17579  }
17580 
17581  /* panel header */
17582  if (nk_panel_has_header(win->flags, title))
17583  {
17584  struct nk_text text;
17585  struct nk_rect header;
17586  const struct nk_style_item *background = 0;
17587 
17588  /* calculate header bounds */
17589  header.x = win->bounds.x;
17590  header.y = win->bounds.y;
17591  header.w = win->bounds.w;
17592  header.h = font->height + 2.0f * style->window.header.padding.y;
17593  header.h += (2.0f * style->window.header.label_padding.y);
17594 
17595  /* shrink panel by header */
17596  layout->header_height = header.h;
17597  layout->bounds.y += header.h;
17598  layout->bounds.h -= header.h;
17599  layout->at_y += header.h;
17600 
17601  /* select correct header background and text color */
17602  if (ctx->active == win) {
17603  background = &style->window.header.active;
17604  text.text = style->window.header.label_active;
17605  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
17606  background = &style->window.header.hover;
17607  text.text = style->window.header.label_hover;
17608  } else {
17609  background = &style->window.header.normal;
17610  text.text = style->window.header.label_normal;
17611  }
17612 
17613  /* draw header background */
17614  header.h += 1.0f;
17615  if (background->type == NK_STYLE_ITEM_IMAGE) {
17616  text.background = nk_rgba(0,0,0,0);
17617  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
17618  } else {
17619  text.background = background->data.color;
17620  nk_fill_rect(out, header, 0, background->data.color);
17621  }
17622 
17623  /* window close button */
17624  {struct nk_rect button;
17625  button.y = header.y + style->window.header.padding.y;
17626  button.h = header.h - 2 * style->window.header.padding.y;
17627  button.w = button.h;
17628  if (win->flags & NK_WINDOW_CLOSABLE) {
17629  nk_flags ws = 0;
17630  if (style->window.header.align == NK_HEADER_RIGHT) {
17631  button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
17632  header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
17633  } else {
17634  button.x = header.x + style->window.header.padding.x;
17635  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17636  }
17637 
17638  if (nk_do_button_symbol(&ws, &win->buffer, button,
17640  &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17641  {
17642  layout->flags |= NK_WINDOW_HIDDEN;
17643  layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
17644  }
17645  }
17646 
17647  /* window minimize button */
17648  if (win->flags & NK_WINDOW_MINIMIZABLE) {
17649  nk_flags ws = 0;
17650  if (style->window.header.align == NK_HEADER_RIGHT) {
17651  button.x = (header.w + header.x) - button.w;
17652  if (!(win->flags & NK_WINDOW_CLOSABLE)) {
17653  button.x -= style->window.header.padding.x;
17654  header.w -= style->window.header.padding.x;
17655  }
17656  header.w -= button.w + style->window.header.spacing.x;
17657  } else {
17658  button.x = header.x;
17659  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17660  }
17661  if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
17663  NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17664  layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
17665  layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
17666  layout->flags | NK_WINDOW_MINIMIZED;
17667  }}
17668 
17669  {/* window header title */
17670  int text_len = nk_strlen(title);
17671  struct nk_rect label = {0,0,0,0};
17672  float t = font->width(font->userdata, font->height, title, text_len);
17673  text.padding = nk_vec2(0,0);
17674 
17675  label.x = header.x + style->window.header.padding.x;
17676  label.x += style->window.header.label_padding.x;
17677  label.y = header.y + style->window.header.label_padding.y;
17678  label.h = font->height + 2 * style->window.header.label_padding.y;
17679  label.w = t + 2 * style->window.header.spacing.x;
17680  label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
17681  nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
17682  }
17683 
17684  /* draw window background */
17685  if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
17686  struct nk_rect body;
17687  body.x = win->bounds.x;
17688  body.w = win->bounds.w;
17689  body.y = (win->bounds.y + layout->header_height);
17690  body.h = (win->bounds.h - layout->header_height);
17692  nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
17693  else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
17694  }
17695 
17696  /* set clipping rectangle */
17697  {struct nk_rect clip;
17698  layout->clip = layout->bounds;
17699  nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
17700  layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
17701  nk_push_scissor(out, clip);
17702  layout->clip = clip;}
17703  return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
17704 }
17705 
17706 NK_INTERN void
17707 nk_panel_end(struct nk_context *ctx)
17708 {
17709  struct nk_input *in;
17710  struct nk_window *window;
17711  struct nk_panel *layout;
17712  const struct nk_style *style;
17713  struct nk_command_buffer *out;
17714 
17715  struct nk_vec2 scrollbar_size;
17716  struct nk_vec2 panel_padding;
17717 
17718  NK_ASSERT(ctx);
17719  NK_ASSERT(ctx->current);
17720  NK_ASSERT(ctx->current->layout);
17721  if (!ctx || !ctx->current || !ctx->current->layout)
17722  return;
17723 
17724  window = ctx->current;
17725  layout = window->layout;
17726  style = &ctx->style;
17727  out = &window->buffer;
17728  in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
17729  if (!nk_panel_is_sub(layout->type))
17730  nk_push_scissor(out, nk_null_rect);
17731 
17732  /* cache configuration data */
17733  scrollbar_size = style->window.scrollbar_size;
17734  panel_padding = nk_panel_get_padding(style, layout->type);
17735 
17736  /* update the current cursor Y-position to point over the last added widget */
17737  layout->at_y += layout->row.height;
17738 
17739  /* dynamic panels */
17740  if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
17741  {
17742  /* update panel height to fit dynamic growth */
17743  struct nk_rect empty_space;
17744  if (layout->at_y < (layout->bounds.y + layout->bounds.h))
17745  layout->bounds.h = layout->at_y - layout->bounds.y;
17746 
17747  /* fill top empty space */
17748  empty_space.x = window->bounds.x;
17749  empty_space.y = layout->bounds.y;
17750  empty_space.h = panel_padding.y;
17751  empty_space.w = window->bounds.w;
17752  nk_fill_rect(out, empty_space, 0, style->window.background);
17753 
17754  /* fill left empty space */
17755  empty_space.x = window->bounds.x;
17756  empty_space.y = layout->bounds.y;
17757  empty_space.w = panel_padding.x + layout->border;
17758  empty_space.h = layout->bounds.h;
17759  nk_fill_rect(out, empty_space, 0, style->window.background);
17760 
17761  /* fill right empty space */
17762  empty_space.x = layout->bounds.x + layout->bounds.w - layout->border;
17763  empty_space.y = layout->bounds.y;
17764  empty_space.w = panel_padding.x + layout->border;
17765  empty_space.h = layout->bounds.h;
17766  if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
17767  empty_space.w += scrollbar_size.x;
17768  nk_fill_rect(out, empty_space, 0, style->window.background);
17769 
17770  /* fill bottom empty space */
17771  if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) {
17772  empty_space.x = window->bounds.x;
17773  empty_space.y = layout->bounds.y + layout->bounds.h;
17774  empty_space.w = window->bounds.w;
17775  empty_space.h = scrollbar_size.y;
17776  nk_fill_rect(out, empty_space, 0, style->window.background);
17777  }
17778  }
17779 
17780  /* scrollbars */
17781  if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
17782  !(layout->flags & NK_WINDOW_MINIMIZED) &&
17784  {
17785  struct nk_rect scroll;
17786  int scroll_has_scrolling;
17787  float scroll_target;
17788  float scroll_offset;
17789  float scroll_step;
17790  float scroll_inc;
17791 
17792  /* mouse wheel scrolling */
17793  if (nk_panel_is_sub(layout->type))
17794  {
17795  /* sub-window mouse wheel scrolling */
17796  struct nk_window *root_window = window;
17797  struct nk_panel *root_panel = window->layout;
17798  while (root_panel->parent)
17799  root_panel = root_panel->parent;
17800  while (root_window->parent)
17801  root_window = root_window->parent;
17802 
17803  /* only allow scrolling if parent window is active */
17804  scroll_has_scrolling = 0;
17805  if ((root_window == ctx->active) && layout->has_scrolling) {
17806  /* and panel is being hovered and inside clip rect*/
17807  if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
17808  NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
17809  root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
17810  {
17811  /* deactivate all parent scrolling */
17812  root_panel = window->layout;
17813  while (root_panel->parent) {
17814  root_panel->has_scrolling = nk_false;
17815  root_panel = root_panel->parent;
17816  }
17817  root_panel->has_scrolling = nk_false;
17818  scroll_has_scrolling = nk_true;
17819  }
17820  }
17821  } else if (!nk_panel_is_sub(layout->type)) {
17822  /* window mouse wheel scrolling */
17823  scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
17824  if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
17825  window->scrolled = nk_true;
17826  else window->scrolled = nk_false;
17827  } else scroll_has_scrolling = nk_false;
17828 
17829  {
17830  /* vertical scrollbar */
17831  nk_flags state = 0;
17832  scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
17833  scroll.y = layout->bounds.y;
17834  scroll.w = scrollbar_size.x;
17835  scroll.h = layout->bounds.h;
17836 
17837  scroll_offset = (float)*layout->offset_y;
17838  scroll_step = scroll.h * 0.10f;
17839  scroll_inc = scroll.h * 0.01f;
17840  scroll_target = (float)(int)(layout->at_y - scroll.y);
17841  scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
17842  scroll_offset, scroll_target, scroll_step, scroll_inc,
17843  &ctx->style.scrollv, in, style->font);
17844  *layout->offset_y = (nk_uint)scroll_offset;
17845  if (in && scroll_has_scrolling)
17846  in->mouse.scroll_delta.y = 0;
17847  }
17848  {
17849  /* horizontal scrollbar */
17850  nk_flags state = 0;
17851  scroll.x = layout->bounds.x;
17852  scroll.y = layout->bounds.y + layout->bounds.h;
17853  scroll.w = layout->bounds.w;
17854  scroll.h = scrollbar_size.y;
17855 
17856  scroll_offset = (float)*layout->offset_x;
17857  scroll_target = (float)(int)(layout->max_x - scroll.x);
17858  scroll_step = layout->max_x * 0.05f;
17859  scroll_inc = layout->max_x * 0.005f;
17860  scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
17861  scroll_offset, scroll_target, scroll_step, scroll_inc,
17862  &ctx->style.scrollh, in, style->font);
17863  *layout->offset_x = (nk_uint)scroll_offset;
17864  }
17865  }
17866 
17867  /* hide scroll if no user input */
17868  if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
17869  int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
17870  int is_window_hovered = nk_window_is_hovered(ctx);
17871  int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
17872  if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
17874  else window->scrollbar_hiding_timer = 0;
17875  } else window->scrollbar_hiding_timer = 0;
17876 
17877  /* window border */
17878  if (layout->flags & NK_WINDOW_BORDER)
17879  {
17880  struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
17881  const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) ?
17882  style->window.border + window->bounds.y + layout->header_height:
17883  (layout->flags & NK_WINDOW_DYNAMIC)?
17884  layout->bounds.y + layout->bounds.h + layout->footer_height:
17885  window->bounds.y + window->bounds.h;
17886 
17887  /* draw border top */
17888  nk_stroke_line(out,window->bounds.x,window->bounds.y,
17889  window->bounds.x + window->bounds.w, window->bounds.y,
17890  layout->border, border_color);
17891 
17892  /* draw bottom border */
17893  nk_stroke_line(out, window->bounds.x, padding_y,
17894  window->bounds.x + window->bounds.w, padding_y, layout->border, border_color);
17895 
17896  /* draw left border */
17897  nk_stroke_line(out, window->bounds.x + layout->border*0.5f,
17898  window->bounds.y, window->bounds.x + layout->border*0.5f,
17899  padding_y, layout->border, border_color);
17900 
17901  /* draw right border */
17902  nk_stroke_line(out, window->bounds.x + window->bounds.w - layout->border*0.5f,
17903  window->bounds.y, window->bounds.x + window->bounds.w - layout->border*0.5f,
17904  padding_y, layout->border, border_color);
17905  }
17906 
17907  /* scaler */
17908  if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
17909  {
17910  /* calculate scaler bounds */
17911  struct nk_rect scaler;
17912  scaler.w = scrollbar_size.x;
17913  scaler.h = scrollbar_size.y;
17914  scaler.y = layout->bounds.y + layout->bounds.h;
17915  if (layout->flags & NK_WINDOW_SCALE_LEFT)
17916  scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
17917  else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
17918  if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
17919  scaler.x -= scaler.w;
17920 
17921  /* draw scaler */
17922  {const struct nk_style_item *item = &style->window.scaler;
17923  if (item->type == NK_STYLE_ITEM_IMAGE)
17924  nk_draw_image(out, scaler, &item->data.image, nk_white);
17925  else {
17926  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
17927  nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
17928  scaler.y + scaler.h, scaler.x + scaler.w,
17929  scaler.y + scaler.h, item->data.color);
17930  } else {
17931  nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
17932  scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
17933  }
17934  }}
17935 
17936  /* do window scaling */
17937  if (!(window->flags & NK_WINDOW_ROM)) {
17938  struct nk_vec2 window_size = style->window.min_size;
17939  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
17940  int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
17941  NK_BUTTON_LEFT, scaler, nk_true);
17942 
17943  if (left_mouse_down && left_mouse_click_in_scaler) {
17944  float delta_x = in->mouse.delta.x;
17945  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
17946  delta_x = -delta_x;
17947  window->bounds.x += in->mouse.delta.x;
17948  }
17949  /* dragging in x-direction */
17950  if (window->bounds.w + delta_x >= window_size.x) {
17951  if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
17952  window->bounds.w = window->bounds.w + delta_x;
17953  scaler.x += in->mouse.delta.x;
17954  }
17955  }
17956  /* dragging in y-direction (only possible if static window) */
17957  if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
17958  if (window_size.y < window->bounds.h + in->mouse.delta.y) {
17959  if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
17960  window->bounds.h = window->bounds.h + in->mouse.delta.y;
17961  scaler.y += in->mouse.delta.y;
17962  }
17963  }
17964  }
17966  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
17967  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
17968  }
17969  }
17970  }
17971  if (!nk_panel_is_sub(layout->type)) {
17972  /* window is hidden so clear command buffer */
17973  if (layout->flags & NK_WINDOW_HIDDEN)
17974  nk_command_buffer_reset(&window->buffer);
17975  /* window is visible and not tab */
17976  else nk_finish(ctx, window);
17977  }
17978 
17979  /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
17980  if (layout->flags & NK_WINDOW_REMOVE_ROM) {
17981  layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
17982  layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
17983  }
17984  window->flags = layout->flags;
17985 
17986  /* property garbage collector */
17987  if (window->property.active && window->property.old != window->property.seq &&
17988  window->property.active == window->property.prev) {
17989  nk_zero(&window->property, sizeof(window->property));
17990  } else {
17991  window->property.old = window->property.seq;
17992  window->property.prev = window->property.active;
17993  window->property.seq = 0;
17994  }
17995  /* edit garbage collector */
17996  if (window->edit.active && window->edit.old != window->edit.seq &&
17997  window->edit.active == window->edit.prev) {
17998  nk_zero(&window->edit, sizeof(window->edit));
17999  } else {
18000  window->edit.old = window->edit.seq;
18001  window->edit.prev = window->edit.active;
18002  window->edit.seq = 0;
18003  }
18004  /* contextual garbage collector */
18005  if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
18006  window->popup.con_count = 0;
18007  window->popup.con_old = 0;
18008  window->popup.active_con = 0;
18009  } else {
18010  window->popup.con_old = window->popup.con_count;
18011  window->popup.con_count = 0;
18012  }
18013  window->popup.combo_count = 0;
18014  /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
18015  NK_ASSERT(!layout->row.tree_depth);
18016 }
18017 
18018 /* ----------------------------------------------------------------
18019  *
18020  * PAGE ELEMENT
18021  *
18022  * ---------------------------------------------------------------*/
18023 NK_INTERN struct nk_page_element*
18024 nk_create_page_element(struct nk_context *ctx)
18025 {
18026  struct nk_page_element *elem;
18027  if (ctx->freelist) {
18028  /* unlink page element from free list */
18029  elem = ctx->freelist;
18030  ctx->freelist = elem->next;
18031  } else if (ctx->use_pool) {
18032  /* allocate page element from memory pool */
18033  elem = nk_pool_alloc(&ctx->pool);
18034  NK_ASSERT(elem);
18035  if (!elem) return 0;
18036  } else {
18037  /* allocate new page element from back of fixed size memory buffer */
18038  NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
18039  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
18040  elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
18041  NK_ASSERT(elem);
18042  if (!elem) return 0;
18043  }
18044  nk_zero_struct(*elem);
18045  elem->next = 0;
18046  elem->prev = 0;
18047  return elem;
18048 }
18049 
18050 NK_INTERN void
18051 nk_link_page_element_into_freelist(struct nk_context *ctx,
18052  struct nk_page_element *elem)
18053 {
18054  /* link table into freelist */
18055  if (!ctx->freelist) {
18056  ctx->freelist = elem;
18057  } else {
18058  elem->next = ctx->freelist;
18059  ctx->freelist = elem;
18060  }
18061 }
18062 
18063 NK_INTERN void
18064 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
18065 {
18066  /* we have a pool so just add to free list */
18067  if (ctx->use_pool) {
18068  nk_link_page_element_into_freelist(ctx, elem);
18069  return;
18070  }
18071  /* if possible remove last element from back of fixed memory buffer */
18072  {void *elem_end = (void*)(elem + 1);
18073  void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
18074  if (elem_end == buffer_end)
18075  ctx->memory.size -= sizeof(struct nk_page_element);
18076  else nk_link_page_element_into_freelist(ctx, elem);}
18077 }
18078 
18079 /* ----------------------------------------------------------------
18080  *
18081  * PANEL
18082  *
18083  * ---------------------------------------------------------------*/
18084 NK_INTERN void*
18085 nk_create_panel(struct nk_context *ctx)
18086 {
18087  struct nk_page_element *elem;
18088  elem = nk_create_page_element(ctx);
18089  if (!elem) return 0;
18090  nk_zero_struct(*elem);
18091  return &elem->data.pan;
18092 }
18093 
18094 NK_INTERN void
18095 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
18096 {
18097  union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
18098  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18099  nk_free_page_element(ctx, pe);
18100 }
18101 
18102 /* ----------------------------------------------------------------
18103  *
18104  * TABLES
18105  *
18106  * ---------------------------------------------------------------*/
18107 NK_INTERN struct nk_table*
18108 nk_create_table(struct nk_context *ctx)
18109 {
18110  struct nk_page_element *elem;
18111  elem = nk_create_page_element(ctx);
18112  if (!elem) return 0;
18113  nk_zero_struct(*elem);
18114  return &elem->data.tbl;
18115 }
18116 
18117 NK_INTERN void
18118 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
18119 {
18120  union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
18121  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18122  nk_free_page_element(ctx, pe);
18123 }
18124 
18125 NK_INTERN void
18126 nk_push_table(struct nk_window *win, struct nk_table *tbl)
18127 {
18128  if (!win->tables) {
18129  win->tables = tbl;
18130  tbl->next = 0;
18131  tbl->prev = 0;
18132  win->table_count = 1;
18133  win->table_size = 0;
18134  return;
18135  }
18136  win->tables->prev = tbl;
18137  tbl->next = win->tables;
18138  tbl->prev = 0;
18139  win->tables = tbl;
18140  win->table_count++;
18141  win->table_size = 0;
18142 }
18143 
18144 NK_INTERN void
18145 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
18146 {
18147  if (win->tables == tbl)
18148  win->tables = tbl->next;
18149  if (tbl->next)
18150  tbl->next->prev = tbl->prev;
18151  if (tbl->prev)
18152  tbl->prev->next = tbl->next;
18153  tbl->next = 0;
18154  tbl->prev = 0;
18155 }
18156 
18157 NK_INTERN nk_uint*
18158 nk_add_value(struct nk_context *ctx, struct nk_window *win,
18159  nk_hash name, nk_uint value)
18160 {
18161  NK_ASSERT(ctx);
18162  NK_ASSERT(win);
18163  if (!win || !ctx) return 0;
18164  if (!win->tables || win->table_size >= NK_VALUE_PAGE_CAPACITY) {
18165  struct nk_table *tbl = nk_create_table(ctx);
18166  NK_ASSERT(tbl);
18167  if (!tbl) return 0;
18168  nk_push_table(win, tbl);
18169  }
18170  win->tables->seq = win->seq;
18171  win->tables->keys[win->table_size] = name;
18172  win->tables->values[win->table_size] = value;
18173  return &win->tables->values[win->table_size++];
18174 }
18175 
18176 NK_INTERN nk_uint*
18177 nk_find_value(struct nk_window *win, nk_hash name)
18178 {
18179  nk_ushort size = win->table_size;
18180  struct nk_table *iter = win->tables;
18181  while (iter) {
18182  nk_ushort i = 0;
18183  for (i = 0; i < size; ++i) {
18184  if (iter->keys[i] == name) {
18185  iter->seq = win->seq;
18186  return &iter->values[i];
18187  }
18188  }
18189  size = NK_VALUE_PAGE_CAPACITY;
18190  iter = iter->next;
18191  }
18192  return 0;
18193 }
18194 
18195 /* ----------------------------------------------------------------
18196  *
18197  * WINDOW
18198  *
18199  * ---------------------------------------------------------------*/
18200 NK_INTERN void*
18201 nk_create_window(struct nk_context *ctx)
18202 {
18203  struct nk_page_element *elem;
18204  elem = nk_create_page_element(ctx);
18205  if (!elem) return 0;
18206  elem->data.win.seq = ctx->seq;
18207  return &elem->data.win;
18208 }
18209 
18210 NK_INTERN void
18211 nk_free_window(struct nk_context *ctx, struct nk_window *win)
18212 {
18213  /* unlink windows from list */
18214  struct nk_table *it = win->tables;
18215  if (win->popup.win) {
18216  nk_free_window(ctx, win->popup.win);
18217  win->popup.win = 0;
18218  }
18219  win->next = 0;
18220  win->prev = 0;
18221 
18222  while (it) {
18223  /*free window state tables */
18224  struct nk_table *n = it->next;
18225  nk_remove_table(win, it);
18226  nk_free_table(ctx, it);
18227  if (it == win->tables)
18228  win->tables = n;
18229  it = n;
18230  }
18231 
18232  /* link windows into freelist */
18233  {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
18234  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18235  nk_free_page_element(ctx, pe);}
18236 }
18237 
18238 NK_INTERN struct nk_window*
18239 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
18240 {
18241  struct nk_window *iter;
18242  iter = ctx->begin;
18243  while (iter) {
18244  NK_ASSERT(iter != iter->next);
18245  if (iter->name == hash) {
18246  int max_len = nk_strlen(iter->name_string);
18247  if (!nk_stricmpn(iter->name_string, name, max_len))
18248  return iter;
18249  }
18250  iter = iter->next;
18251  }
18252  return 0;
18253 }
18254 
18255 enum nk_window_insert_location {
18256  NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
18257  NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
18258 };
18259 NK_INTERN void
18260 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
18261  enum nk_window_insert_location loc)
18262 {
18263  const struct nk_window *iter;
18264  NK_ASSERT(ctx);
18265  NK_ASSERT(win);
18266  if (!win || !ctx) return;
18267 
18268  iter = ctx->begin;
18269  while (iter) {
18270  NK_ASSERT(iter != iter->next);
18271  NK_ASSERT(iter != win);
18272  if (iter == win) return;
18273  iter = iter->next;
18274  }
18275 
18276  if (!ctx->begin) {
18277  win->next = 0;
18278  win->prev = 0;
18279  ctx->begin = win;
18280  ctx->end = win;
18281  ctx->count = 1;
18282  return;
18283  }
18284  if (loc == NK_INSERT_BACK) {
18285  struct nk_window *end;
18286  end = ctx->end;
18287  end->flags |= NK_WINDOW_ROM;
18288  end->next = win;
18289  win->prev = ctx->end;
18290  win->next = 0;
18291  ctx->end = win;
18292  ctx->active = ctx->end;
18293  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18294  } else {
18295  //ctx->end->flags |= NK_WINDOW_ROM;
18296  ctx->begin->prev = win;
18297  win->next = ctx->begin;
18298  win->prev = 0;
18299  ctx->begin = win;
18300  ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
18301  }
18302  ctx->count++;
18303 }
18304 
18305 NK_INTERN void
18306 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
18307 {
18308  if (win == ctx->begin || win == ctx->end) {
18309  if (win == ctx->begin) {
18310  ctx->begin = win->next;
18311  if (win->next)
18312  win->next->prev = 0;
18313  }
18314  if (win == ctx->end) {
18315  ctx->end = win->prev;
18316  if (win->prev)
18317  win->prev->next = 0;
18318  }
18319  } else {
18320  if (win->next)
18321  win->next->prev = win->prev;
18322  if (win->prev)
18323  win->prev->next = win->next;
18324  }
18325  if (win == ctx->active || !ctx->active) {
18326  ctx->active = ctx->end;
18327  if (ctx->end)
18328  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18329  }
18330  win->next = 0;
18331  win->prev = 0;
18332  ctx->count--;
18333 }
18334 
18335 NK_API int
18336 nk_begin(struct nk_context *ctx, const char *title,
18337  struct nk_rect bounds, nk_flags flags)
18338 {
18339  return nk_begin_titled(ctx, title, title, bounds, flags);
18340 }
18341 
18342 NK_API int
18343 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
18344  struct nk_rect bounds, nk_flags flags)
18345 {
18346  struct nk_window *win;
18347  struct nk_style *style;
18348  nk_hash title_hash;
18349  int title_len;
18350  int ret = 0;
18351 
18352  NK_ASSERT(ctx);
18353  NK_ASSERT(name);
18354  NK_ASSERT(title);
18355  NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
18356  NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
18357  if (!ctx || ctx->current || !title || !name)
18358  return 0;
18359 
18360  /* find or create window */
18361  style = &ctx->style;
18362  title_len = (int)nk_strlen(name);
18363  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18364  win = nk_find_window(ctx, title_hash, name);
18365  if (!win) {
18366  /* create new window */
18367  nk_size name_length = (nk_size)nk_strlen(name);
18368  win = (struct nk_window*)nk_create_window(ctx);
18369  NK_ASSERT(win);
18370  if (!win) return 0;
18371 
18372  if (flags & NK_WINDOW_BACKGROUND)
18373  nk_insert_window(ctx, win, NK_INSERT_FRONT);
18374  else nk_insert_window(ctx, win, NK_INSERT_BACK);
18375  nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
18376 
18377  win->flags = flags;
18378  win->bounds = bounds;
18379  win->name = title_hash;
18380  name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
18381  NK_MEMCPY(win->name_string, name, name_length);
18382  win->name_string[name_length] = 0;
18383  win->popup.win = 0;
18384  if (!ctx->active)
18385  ctx->active = win;
18386  } else {
18387  /* update window */
18388  win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
18389  win->flags |= flags;
18390  if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
18391  win->bounds = bounds;
18392  /* If this assert triggers you either:
18393  *
18394  * I.) Have more than one window with the same name or
18395  * II.) You forgot to actually draw the window.
18396  * More specific you did not call `nk_clear` (nk_clear will be
18397  * automatically called for you if you are using one of the
18398  * provided demo backends). */
18399  NK_ASSERT(win->seq != ctx->seq);
18400  win->seq = ctx->seq;
18401  if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN))
18402  ctx->active = win;
18403  }
18404  if (win->flags & NK_WINDOW_HIDDEN) {
18405  ctx->current = win;
18406  win->layout = 0;
18407  return 0;
18408  }
18409 
18410  /* window overlapping */
18411  if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
18412  {
18413  int inpanel, ishovered;
18414  const struct nk_window *iter = win;
18415  float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
18416  (2.0f * style->window.header.label_padding.y);
18417  struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
18418  win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
18419 
18420  /* activate window if hovered and no other window is overlapping this window */
18421  nk_start(ctx, win);
18422  inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
18423  inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
18424  ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
18425  if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
18426  iter = win->next;
18427  while (iter) {
18428  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18429  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18430  if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18431  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18432  (!(iter->flags & NK_WINDOW_HIDDEN) || !(iter->flags & NK_WINDOW_BACKGROUND)))
18433  break;
18434 
18435  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18436  NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18437  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18438  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18439  break;
18440  iter = iter->next;
18441  }
18442  }
18443 
18444  /* activate window if clicked */
18445  if (iter && inpanel && (win != ctx->end) && !(iter->flags & NK_WINDOW_BACKGROUND)) {
18446  iter = win->next;
18447  while (iter) {
18448  /* try to find a panel with higher priority in the same position */
18449  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18450  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18451  if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
18452  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18453  !(iter->flags & NK_WINDOW_HIDDEN))
18454  break;
18455  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18456  NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18457  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18458  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18459  break;
18460  iter = iter->next;
18461  }
18462  }
18463 
18464  if (!iter && ctx->end != win) {
18465  if (!(win->flags & NK_WINDOW_BACKGROUND)) {
18466  /* current window is active in that position so transfer to top
18467  * at the highest priority in stack */
18468  nk_remove_window(ctx, win);
18469  nk_insert_window(ctx, win, NK_INSERT_BACK);
18470  }
18471  win->flags &= ~(nk_flags)NK_WINDOW_ROM;
18472  ctx->active = win;
18473  }
18474  if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
18475  win->flags |= NK_WINDOW_ROM;
18476  }
18477 
18478  win->layout = (struct nk_panel*)nk_create_panel(ctx);
18479  ctx->current = win;
18480  ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
18481  win->layout->offset_x = &win->scrollbar.x;
18482  win->layout->offset_y = &win->scrollbar.y;
18483  return ret;
18484 }
18485 
18486 NK_API void
18487 nk_end(struct nk_context *ctx)
18488 {
18489  struct nk_panel *layout;
18490  NK_ASSERT(ctx);
18491  NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
18492  if (!ctx || !ctx->current)
18493  return;
18494 
18495  layout = ctx->current->layout;
18496  if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
18497  ctx->current = 0;
18498  return;
18499  }
18500  nk_panel_end(ctx);
18501  nk_free_panel(ctx, ctx->current->layout);
18502  ctx->current = 0;
18503 }
18504 
18505 NK_API struct nk_rect
18507 {
18508  NK_ASSERT(ctx);
18509  NK_ASSERT(ctx->current);
18510  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18511  return ctx->current->bounds;
18512 }
18513 
18514 NK_API struct nk_vec2
18516 {
18517  NK_ASSERT(ctx);
18518  NK_ASSERT(ctx->current);
18519  if (!ctx || !ctx->current) return nk_vec2(0,0);
18520  return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
18521 }
18522 
18523 NK_API struct nk_vec2
18525 {
18526  NK_ASSERT(ctx);
18527  NK_ASSERT(ctx->current);
18528  if (!ctx || !ctx->current) return nk_vec2(0,0);
18529  return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
18530 }
18531 
18532 NK_API float
18533 nk_window_get_width(const struct nk_context *ctx)
18534 {
18535  NK_ASSERT(ctx);
18536  NK_ASSERT(ctx->current);
18537  if (!ctx || !ctx->current) return 0;
18538  return ctx->current->bounds.w;
18539 }
18540 
18541 NK_API float
18542 nk_window_get_height(const struct nk_context *ctx)
18543 {
18544  NK_ASSERT(ctx);
18545  NK_ASSERT(ctx->current);
18546  if (!ctx || !ctx->current) return 0;
18547  return ctx->current->bounds.h;
18548 }
18549 
18550 NK_API struct nk_rect
18552 {
18553  NK_ASSERT(ctx);
18554  NK_ASSERT(ctx->current);
18555  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18556  return ctx->current->layout->clip;
18557 }
18558 
18559 NK_API struct nk_vec2
18561 {
18562  NK_ASSERT(ctx);
18563  NK_ASSERT(ctx->current);
18564  NK_ASSERT(ctx->current->layout);
18565  if (!ctx || !ctx->current) return nk_vec2(0,0);
18566  return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
18567 }
18568 
18569 NK_API struct nk_vec2
18571 {
18572  NK_ASSERT(ctx);
18573  NK_ASSERT(ctx->current);
18574  NK_ASSERT(ctx->current->layout);
18575  if (!ctx || !ctx->current) return nk_vec2(0,0);
18576  return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
18577  ctx->current->layout->clip.y + ctx->current->layout->clip.h);
18578 }
18579 
18580 NK_API struct nk_vec2
18582 {
18583  NK_ASSERT(ctx);
18584  NK_ASSERT(ctx->current);
18585  NK_ASSERT(ctx->current->layout);
18586  if (!ctx || !ctx->current) return nk_vec2(0,0);
18587  return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
18588 }
18589 
18590 NK_API struct nk_command_buffer*
18591 nk_window_get_canvas(struct nk_context *ctx)
18592 {
18593  NK_ASSERT(ctx);
18594  NK_ASSERT(ctx->current);
18595  NK_ASSERT(ctx->current->layout);
18596  if (!ctx || !ctx->current) return 0;
18597  return &ctx->current->buffer;
18598 }
18599 
18600 NK_API struct nk_panel*
18601 nk_window_get_panel(struct nk_context *ctx)
18602 {
18603  NK_ASSERT(ctx);
18604  NK_ASSERT(ctx->current);
18605  if (!ctx || !ctx->current) return 0;
18606  return ctx->current->layout;
18607 }
18608 
18609 NK_API int
18610 nk_window_has_focus(const struct nk_context *ctx)
18611 {
18612  NK_ASSERT(ctx);
18613  NK_ASSERT(ctx->current);
18614  NK_ASSERT(ctx->current->layout);
18615  if (!ctx || !ctx->current) return 0;
18616  return ctx->current == ctx->active;
18617 }
18618 
18619 NK_API int
18620 nk_window_is_hovered(struct nk_context *ctx)
18621 {
18622  NK_ASSERT(ctx);
18623  NK_ASSERT(ctx->current);
18624  if (!ctx || !ctx->current) return 0;
18625  return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
18626 }
18627 
18628 NK_API int
18630 {
18631  struct nk_window *iter;
18632  NK_ASSERT(ctx);
18633  if (!ctx) return 0;
18634  iter = ctx->begin;
18635  while (iter) {
18636  /* check if window is being hovered */
18637  if (iter->flags & NK_WINDOW_MINIMIZED) {
18638  struct nk_rect header = iter->bounds;
18639  header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
18640  if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
18641  return 1;
18642  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
18643  return 1;
18644  }
18645  /* check if window popup is being hovered */
18646  if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
18647  return 1;
18648  iter = iter->next;
18649  }
18650  return 0;
18651 }
18652 
18653 NK_API int
18654 nk_item_is_any_active(struct nk_context *ctx)
18655 {
18656  int any_hovered = nk_window_is_any_hovered(ctx);
18657  int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
18658  return any_hovered || any_active;
18659 }
18660 
18661 NK_API int
18662 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
18663 {
18664  int title_len;
18665  nk_hash title_hash;
18666  struct nk_window *win;
18667  NK_ASSERT(ctx);
18668  if (!ctx) return 0;
18669 
18670  title_len = (int)nk_strlen(name);
18671  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18672  win = nk_find_window(ctx, title_hash, name);
18673  if (!win) return 0;
18674  return win->flags & NK_WINDOW_MINIMIZED;
18675 }
18676 
18677 NK_API int
18678 nk_window_is_closed(struct nk_context *ctx, const char *name)
18679 {
18680  int title_len;
18681  nk_hash title_hash;
18682  struct nk_window *win;
18683  NK_ASSERT(ctx);
18684  if (!ctx) return 1;
18685 
18686  title_len = (int)nk_strlen(name);
18687  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18688  win = nk_find_window(ctx, title_hash, name);
18689  if (!win) return 1;
18690  return (win->flags & NK_WINDOW_CLOSED);
18691 }
18692 
18693 NK_API int
18694 nk_window_is_hidden(struct nk_context *ctx, const char *name)
18695 {
18696  int title_len;
18697  nk_hash title_hash;
18698  struct nk_window *win;
18699  NK_ASSERT(ctx);
18700  if (!ctx) return 1;
18701 
18702  title_len = (int)nk_strlen(name);
18703  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18704  win = nk_find_window(ctx, title_hash, name);
18705  if (!win) return 1;
18706  return (win->flags & NK_WINDOW_HIDDEN);
18707 }
18708 
18709 NK_API int
18710 nk_window_is_active(struct nk_context *ctx, const char *name)
18711 {
18712  int title_len;
18713  nk_hash title_hash;
18714  struct nk_window *win;
18715  NK_ASSERT(ctx);
18716  if (!ctx) return 0;
18717 
18718  title_len = (int)nk_strlen(name);
18719  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18720  win = nk_find_window(ctx, title_hash, name);
18721  if (!win) return 0;
18722  return win == ctx->active;
18723 }
18724 
18725 NK_API struct nk_window*
18726 nk_window_find(struct nk_context *ctx, const char *name)
18727 {
18728  int title_len;
18729  nk_hash title_hash;
18730  title_len = (int)nk_strlen(name);
18731  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18732  return nk_find_window(ctx, title_hash, name);
18733 }
18734 
18735 NK_API void
18736 nk_window_close(struct nk_context *ctx, const char *name)
18737 {
18738  struct nk_window *win;
18739  NK_ASSERT(ctx);
18740  if (!ctx) return;
18741  win = nk_window_find(ctx, name);
18742  if (!win) return;
18743  NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
18744  if (ctx->current == win) return;
18745  win->flags |= NK_WINDOW_HIDDEN;
18746  win->flags |= NK_WINDOW_CLOSED;
18747 }
18748 
18749 NK_API void
18750 nk_window_set_bounds(struct nk_context *ctx, struct nk_rect bounds)
18751 {
18752  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18753  if (!ctx || !ctx->current) return;
18754  ctx->current->bounds = bounds;
18755 }
18756 
18757 NK_API void
18758 nk_window_set_position(struct nk_context *ctx, struct nk_vec2 pos)
18759 {
18760  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18761  if (!ctx || !ctx->current) return;
18762  ctx->current->bounds.x = pos.x;
18763  ctx->current->bounds.y = pos.y;
18764 }
18765 
18766 NK_API void
18767 nk_window_set_size(struct nk_context *ctx, struct nk_vec2 size)
18768 {
18769  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18770  if (!ctx || !ctx->current) return;
18771  ctx->current->bounds.w = size.x;
18772  ctx->current->bounds.h = size.y;
18773 }
18774 
18775 NK_API void
18776 nk_window_collapse(struct nk_context *ctx, const char *name,
18777  enum nk_collapse_states c)
18778 {
18779  int title_len;
18780  nk_hash title_hash;
18781  struct nk_window *win;
18782  NK_ASSERT(ctx);
18783  if (!ctx) return;
18784 
18785  title_len = (int)nk_strlen(name);
18786  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18787  win = nk_find_window(ctx, title_hash, name);
18788  if (!win) return;
18789  if (c == NK_MINIMIZED)
18790  win->flags |= NK_WINDOW_MINIMIZED;
18791  else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
18792 }
18793 
18794 NK_API void
18795 nk_window_collapse_if(struct nk_context *ctx, const char *name,
18796  enum nk_collapse_states c, int cond)
18797 {
18798  NK_ASSERT(ctx);
18799  if (!ctx || !cond) return;
18800  nk_window_collapse(ctx, name, c);
18801 }
18802 
18803 NK_API void
18804 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
18805 {
18806  int title_len;
18807  nk_hash title_hash;
18808  struct nk_window *win;
18809  NK_ASSERT(ctx);
18810  if (!ctx) return;
18811 
18812  title_len = (int)nk_strlen(name);
18813  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18814  win = nk_find_window(ctx, title_hash, name);
18815  if (!win) return;
18816  if (s == NK_HIDDEN) {
18817  win->flags |= NK_WINDOW_HIDDEN;
18818  } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
18819 }
18820 
18821 NK_API void
18822 nk_window_show_if(struct nk_context *ctx, const char *name,
18823  enum nk_show_states s, int cond)
18824 {
18825  NK_ASSERT(ctx);
18826  if (!ctx || !cond) return;
18827  nk_window_show(ctx, name, s);
18828 }
18829 
18830 NK_API void
18831 nk_window_set_focus(struct nk_context *ctx, const char *name)
18832 {
18833  int title_len;
18834  nk_hash title_hash;
18835  struct nk_window *win;
18836  NK_ASSERT(ctx);
18837  if (!ctx) return;
18838 
18839  title_len = (int)nk_strlen(name);
18840  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18841  win = nk_find_window(ctx, title_hash, name);
18842  if (win && ctx->end != win) {
18843  nk_remove_window(ctx, win);
18844  nk_insert_window(ctx, win, NK_INSERT_BACK);
18845  }
18846  ctx->active = win;
18847 }
18848 
18849 /*----------------------------------------------------------------
18850  *
18851  * MENUBAR
18852  *
18853  * --------------------------------------------------------------*/
18854 NK_API void
18855 nk_menubar_begin(struct nk_context *ctx)
18856 {
18857  struct nk_panel *layout;
18858  NK_ASSERT(ctx);
18859  NK_ASSERT(ctx->current);
18860  NK_ASSERT(ctx->current->layout);
18861  if (!ctx || !ctx->current || !ctx->current->layout)
18862  return;
18863 
18864  layout = ctx->current->layout;
18865  NK_ASSERT(layout->at_y == layout->bounds.y);
18866  /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
18867  If you want a menubar the first nuklear function after `nk_begin` has to be a
18868  `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
18869  widgets (also supports multiple rows).
18870  Example:
18871  if (nk_begin(...)) {
18872  nk_menubar_begin(...);
18873  nk_layout_xxxx(...);
18874  nk_button(...);
18875  nk_layout_xxxx(...);
18876  nk_button(...);
18877  nk_menubar_end(...);
18878  }
18879  nk_end(...);
18880  */
18881  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
18882  return;
18883 
18884  layout->menu.x = layout->at_x;
18885  layout->menu.y = layout->at_y + layout->row.height;
18886  layout->menu.w = layout->bounds.w;
18887  layout->menu.offset.x = *layout->offset_x;
18888  layout->menu.offset.y = *layout->offset_y;
18889  *layout->offset_y = 0;
18890 }
18891 
18892 NK_API void
18893 nk_menubar_end(struct nk_context *ctx)
18894 {
18895  struct nk_window *win;
18896  struct nk_panel *layout;
18897  struct nk_command_buffer *out;
18898 
18899  NK_ASSERT(ctx);
18900  NK_ASSERT(ctx->current);
18901  NK_ASSERT(ctx->current->layout);
18902  if (!ctx || !ctx->current || !ctx->current->layout)
18903  return;
18904 
18905  win = ctx->current;
18906  out = &win->buffer;
18907  layout = win->layout;
18908  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
18909  return;
18910 
18911  layout->menu.h = layout->at_y - layout->menu.y;
18912  layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
18913  layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
18914 
18915  *layout->offset_x = layout->menu.offset.x;
18916  *layout->offset_y = layout->menu.offset.y;
18917  layout->at_y = layout->bounds.y - layout->row.height;
18918 
18919  layout->clip.y = layout->bounds.y;
18920  layout->clip.h = layout->bounds.h;
18921  nk_push_scissor(out, layout->clip);
18922 }
18923 /* -------------------------------------------------------------
18924  *
18925  * LAYOUT
18926  *
18927  * --------------------------------------------------------------*/
18928 NK_INTERN float
18929 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
18930  float total_space, int columns)
18931 {
18932  float panel_padding;
18933  float panel_spacing;
18934  float panel_space;
18935 
18936  struct nk_vec2 spacing;
18937  struct nk_vec2 padding;
18938 
18939  spacing = style->window.spacing;
18940  padding = nk_panel_get_padding(style, type);
18941 
18942  /* calculate the usable panel space */
18943  panel_padding = 2 * padding.x;
18944  panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
18945  panel_space = total_space - panel_padding - panel_spacing;
18946  return panel_space;
18947 }
18948 
18949 NK_INTERN void
18950 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
18951  float height, int cols)
18952 {
18953  struct nk_panel *layout;
18954  const struct nk_style *style;
18955  struct nk_command_buffer *out;
18956 
18957  struct nk_vec2 item_spacing;
18958  struct nk_color color;
18959 
18960  NK_ASSERT(ctx);
18961  NK_ASSERT(ctx->current);
18962  NK_ASSERT(ctx->current->layout);
18963  if (!ctx || !ctx->current || !ctx->current->layout)
18964  return;
18965 
18966  /* prefetch some configuration data */
18967  layout = win->layout;
18968  style = &ctx->style;
18969  out = &win->buffer;
18970  color = style->window.background;
18971  item_spacing = style->window.spacing;
18972 
18973  /* if one of these triggers you forgot to add an `if` condition around either
18974  a window, group, popup, combobox or contextual menu `begin` and `end` block.
18975  Example:
18976  if (nk_begin(...) {...} nk_end(...); or
18977  if (nk_group_begin(...) { nk_group_end(...);} */
18978  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
18979  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
18980  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
18981 
18982  /* update the current row and set the current row layout */
18983  layout->row.index = 0;
18984  layout->at_y += layout->row.height;
18985  layout->row.columns = cols;
18986  layout->row.height = height + item_spacing.y;
18987  layout->row.item_offset = 0;
18988  if (layout->flags & NK_WINDOW_DYNAMIC) {
18989  /* draw background for dynamic panels */
18990  struct nk_rect background;
18991  background.x = win->bounds.x;
18992  background.w = win->bounds.w;
18993  background.y = layout->at_y - 1.0f;
18994  background.h = layout->row.height + 1.0f;
18995  nk_fill_rect(out, background, 0, color);
18996  }
18997 }
18998 
18999 NK_INTERN void
19000 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
19001  float height, int cols, int width)
19002 {
19003  /* update the current row and set the current row layout */
19004  struct nk_window *win;
19005  NK_ASSERT(ctx);
19006  NK_ASSERT(ctx->current);
19007  NK_ASSERT(ctx->current->layout);
19008  if (!ctx || !ctx->current || !ctx->current->layout)
19009  return;
19010 
19011  win = ctx->current;
19012  nk_panel_layout(ctx, win, height, cols);
19013  if (fmt == NK_DYNAMIC)
19015  else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
19016 
19017  win->layout->row.ratio = 0;
19018  win->layout->row.filled = 0;
19019  win->layout->row.item_offset = 0;
19020  win->layout->row.item_width = (float)width;
19021 }
19022 
19023 NK_API float
19024 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
19025 {
19026  struct nk_window *win;
19027  NK_ASSERT(ctx);
19028  NK_ASSERT(pixel_width);
19029  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
19030  win = ctx->current;
19031  return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
19032 }
19033 
19034 NK_API void
19035 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
19036 {
19037  nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
19038 }
19039 
19040 NK_API void
19041 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
19042 {
19043  nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
19044 }
19045 
19046 NK_API void
19047 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
19048  float row_height, int cols)
19049 {
19050  struct nk_window *win;
19051  struct nk_panel *layout;
19052 
19053  NK_ASSERT(ctx);
19054  NK_ASSERT(ctx->current);
19055  NK_ASSERT(ctx->current->layout);
19056  if (!ctx || !ctx->current || !ctx->current->layout)
19057  return;
19058 
19059  win = ctx->current;
19060  layout = win->layout;
19061  nk_panel_layout(ctx, win, row_height, cols);
19062  if (fmt == NK_DYNAMIC)
19063  layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
19064  else layout->row.type = NK_LAYOUT_STATIC_ROW;
19065 
19066  layout->row.ratio = 0;
19067  layout->row.filled = 0;
19068  layout->row.item_width = 0;
19069  layout->row.item_offset = 0;
19070  layout->row.columns = cols;
19071 }
19072 
19073 NK_API void
19074 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
19075 {
19076  struct nk_window *win;
19077  struct nk_panel *layout;
19078 
19079  NK_ASSERT(ctx);
19080  NK_ASSERT(ctx->current);
19081  NK_ASSERT(ctx->current->layout);
19082  if (!ctx || !ctx->current || !ctx->current->layout)
19083  return;
19084 
19085  win = ctx->current;
19086  layout = win->layout;
19087  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19088  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19089  return;
19090 
19091  if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
19092  float ratio = ratio_or_width;
19093  if ((ratio + layout->row.filled) > 1.0f) return;
19094  if (ratio > 0.0f)
19095  layout->row.item_width = NK_SATURATE(ratio);
19096  else layout->row.item_width = 1.0f - layout->row.filled;
19097  } else layout->row.item_width = ratio_or_width;
19098 }
19099 
19100 NK_API void
19101 nk_layout_row_end(struct nk_context *ctx)
19102 {
19103  struct nk_window *win;
19104  struct nk_panel *layout;
19105 
19106  NK_ASSERT(ctx);
19107  NK_ASSERT(ctx->current);
19108  NK_ASSERT(ctx->current->layout);
19109  if (!ctx || !ctx->current || !ctx->current->layout)
19110  return;
19111 
19112  win = ctx->current;
19113  layout = win->layout;
19114  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19115  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19116  return;
19117  layout->row.item_width = 0;
19118  layout->row.item_offset = 0;
19119 }
19120 
19121 NK_API void
19122 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
19123  float height, int cols, const float *ratio)
19124 {
19125  int i;
19126  int n_undef = 0;
19127  struct nk_window *win;
19128  struct nk_panel *layout;
19129 
19130  NK_ASSERT(ctx);
19131  NK_ASSERT(ctx->current);
19132  NK_ASSERT(ctx->current->layout);
19133  if (!ctx || !ctx->current || !ctx->current->layout)
19134  return;
19135 
19136  win = ctx->current;
19137  layout = win->layout;
19138  nk_panel_layout(ctx, win, height, cols);
19139  if (fmt == NK_DYNAMIC) {
19140  /* calculate width of undefined widget ratios */
19141  float r = 0;
19142  layout->row.ratio = ratio;
19143  for (i = 0; i < cols; ++i) {
19144  if (ratio[i] < 0.0f)
19145  n_undef++;
19146  else r += ratio[i];
19147  }
19148  r = NK_SATURATE(1.0f - r);
19149  layout->row.type = NK_LAYOUT_DYNAMIC;
19150  layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
19151  } else {
19152  layout->row.ratio = ratio;
19153  layout->row.type = NK_LAYOUT_STATIC;
19154  layout->row.item_width = 0;
19155  layout->row.item_offset = 0;
19156  }
19157  layout->row.item_offset = 0;
19158  layout->row.filled = 0;
19159 }
19160 
19161 NK_API void
19162 nk_layout_row_template_begin(struct nk_context *ctx, float height)
19163 {
19164  struct nk_window *win;
19165  struct nk_panel *layout;
19166 
19167  NK_ASSERT(ctx);
19168  NK_ASSERT(ctx->current);
19169  NK_ASSERT(ctx->current->layout);
19170  if (!ctx || !ctx->current || !ctx->current->layout)
19171  return;
19172 
19173  win = ctx->current;
19174  layout = win->layout;
19175  nk_panel_layout(ctx, win, height, 1);
19176  layout->row.type = NK_LAYOUT_TEMPLATE;
19177  layout->row.columns = 0;
19178  layout->row.ratio = 0;
19179  layout->row.item_width = 0;
19180  layout->row.item_height = 0;
19181  layout->row.item_offset = 0;
19182  layout->row.filled = 0;
19183  layout->row.item.x = 0;
19184  layout->row.item.y = 0;
19185  layout->row.item.w = 0;
19186  layout->row.item.h = 0;
19187 }
19188 
19189 NK_API void
19191 {
19192  struct nk_window *win;
19193  struct nk_panel *layout;
19194 
19195  NK_ASSERT(ctx);
19196  NK_ASSERT(ctx->current);
19197  NK_ASSERT(ctx->current->layout);
19198  if (!ctx || !ctx->current || !ctx->current->layout)
19199  return;
19200 
19201  win = ctx->current;
19202  layout = win->layout;
19203  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19204  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19205  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19206  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19207  layout->row.templates[layout->row.columns++] = -1.0f;
19208 }
19209 
19210 NK_API void
19211 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
19212 {
19213  struct nk_window *win;
19214  struct nk_panel *layout;
19215 
19216  NK_ASSERT(ctx);
19217  NK_ASSERT(ctx->current);
19218  NK_ASSERT(ctx->current->layout);
19219  if (!ctx || !ctx->current || !ctx->current->layout)
19220  return;
19221 
19222  win = ctx->current;
19223  layout = win->layout;
19224  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19225  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19226  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19227  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19228  layout->row.templates[layout->row.columns++] = -min_width;
19229 }
19230 
19231 NK_API void
19232 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
19233 {
19234  struct nk_window *win;
19235  struct nk_panel *layout;
19236 
19237  NK_ASSERT(ctx);
19238  NK_ASSERT(ctx->current);
19239  NK_ASSERT(ctx->current->layout);
19240  if (!ctx || !ctx->current || !ctx->current->layout)
19241  return;
19242 
19243  win = ctx->current;
19244  layout = win->layout;
19245  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19246  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19247  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19248  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19249  layout->row.templates[layout->row.columns++] = width;
19250 }
19251 
19252 NK_API void
19254 {
19255  struct nk_window *win;
19256  struct nk_panel *layout;
19257 
19258  int i = 0;
19259  int variable_count = 0;
19260  int min_variable_count = 0;
19261  float min_fixed_width = 0.0f;
19262  float total_fixed_width = 0.0f;
19263  float max_variable_width = 0.0f;
19264 
19265  NK_ASSERT(ctx);
19266  NK_ASSERT(ctx->current);
19267  NK_ASSERT(ctx->current->layout);
19268  if (!ctx || !ctx->current || !ctx->current->layout)
19269  return;
19270 
19271  win = ctx->current;
19272  layout = win->layout;
19273  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19274  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19275  for (i = 0; i < layout->row.columns; ++i) {
19276  float width = layout->row.templates[i];
19277  if (width >= 0.0f) {
19278  total_fixed_width += width;
19279  min_fixed_width += width;
19280  } else if (width < -1.0f) {
19281  width = -width;
19282  total_fixed_width += width;
19283  max_variable_width = NK_MAX(max_variable_width, width);
19284  variable_count++;
19285  } else {
19286  min_variable_count++;
19287  variable_count++;
19288  }
19289  }
19290  if (variable_count) {
19291  float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19292  layout->bounds.w, layout->row.columns);
19293  float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
19294  int enough_space = var_width >= max_variable_width;
19295  if (!enough_space)
19296  var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
19297  for (i = 0; i < layout->row.columns; ++i) {
19298  float *width = &layout->row.templates[i];
19299  *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
19300  }
19301  }
19302 }
19303 
19304 NK_API void
19305 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
19306  float height, int widget_count)
19307 {
19308  struct nk_window *win;
19309  struct nk_panel *layout;
19310 
19311  NK_ASSERT(ctx);
19312  NK_ASSERT(ctx->current);
19313  NK_ASSERT(ctx->current->layout);
19314  if (!ctx || !ctx->current || !ctx->current->layout)
19315  return;
19316 
19317  win = ctx->current;
19318  layout = win->layout;
19319  nk_panel_layout(ctx, win, height, widget_count);
19320  if (fmt == NK_STATIC)
19321  layout->row.type = NK_LAYOUT_STATIC_FREE;
19322  else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
19323 
19324  layout->row.ratio = 0;
19325  layout->row.filled = 0;
19326  layout->row.item_width = 0;
19327  layout->row.item_offset = 0;
19328 }
19329 
19330 NK_API void
19331 nk_layout_space_end(struct nk_context *ctx)
19332 {
19333  struct nk_window *win;
19334  struct nk_panel *layout;
19335 
19336  NK_ASSERT(ctx);
19337  NK_ASSERT(ctx->current);
19338  NK_ASSERT(ctx->current->layout);
19339  if (!ctx || !ctx->current || !ctx->current->layout)
19340  return;
19341 
19342  win = ctx->current;
19343  layout = win->layout;
19344  layout->row.item_width = 0;
19345  layout->row.item_height = 0;
19346  layout->row.item_offset = 0;
19347  nk_zero(&layout->row.item, sizeof(layout->row.item));
19348 }
19349 
19350 NK_API void
19351 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
19352 {
19353  struct nk_window *win;
19354  struct nk_panel *layout;
19355 
19356  NK_ASSERT(ctx);
19357  NK_ASSERT(ctx->current);
19358  NK_ASSERT(ctx->current->layout);
19359  if (!ctx || !ctx->current || !ctx->current->layout)
19360  return;
19361 
19362  win = ctx->current;
19363  layout = win->layout;
19364  layout->row.item = rect;
19365 }
19366 
19367 NK_API struct nk_rect
19369 {
19370  struct nk_rect ret;
19371  struct nk_window *win;
19372  struct nk_panel *layout;
19373 
19374  NK_ASSERT(ctx);
19375  NK_ASSERT(ctx->current);
19376  NK_ASSERT(ctx->current->layout);
19377  win = ctx->current;
19378  layout = win->layout;
19379 
19380  ret.x = layout->clip.x;
19381  ret.y = layout->clip.y;
19382  ret.w = layout->clip.w;
19383  ret.h = layout->row.height;
19384  return ret;
19385 }
19386 
19387 NK_API struct nk_vec2
19388 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
19389 {
19390  struct nk_window *win;
19391  struct nk_panel *layout;
19392 
19393  NK_ASSERT(ctx);
19394  NK_ASSERT(ctx->current);
19395  NK_ASSERT(ctx->current->layout);
19396  win = ctx->current;
19397  layout = win->layout;
19398 
19399  ret.x += layout->at_x - (float)*layout->offset_x;
19400  ret.y += layout->at_y - (float)*layout->offset_y;
19401  return ret;
19402 }
19403 
19404 NK_API struct nk_vec2
19405 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
19406 {
19407  struct nk_window *win;
19408  struct nk_panel *layout;
19409 
19410  NK_ASSERT(ctx);
19411  NK_ASSERT(ctx->current);
19412  NK_ASSERT(ctx->current->layout);
19413  win = ctx->current;
19414  layout = win->layout;
19415 
19416  ret.x += -layout->at_x + (float)*layout->offset_x;
19417  ret.y += -layout->at_y + (float)*layout->offset_y;
19418  return ret;
19419 }
19420 
19421 NK_API struct nk_rect
19423 {
19424  struct nk_window *win;
19425  struct nk_panel *layout;
19426 
19427  NK_ASSERT(ctx);
19428  NK_ASSERT(ctx->current);
19429  NK_ASSERT(ctx->current->layout);
19430  win = ctx->current;
19431  layout = win->layout;
19432 
19433  ret.x += layout->at_x - (float)*layout->offset_x;
19434  ret.y += layout->at_y - (float)*layout->offset_y;
19435  return ret;
19436 }
19437 
19438 NK_API struct nk_rect
19440 {
19441  struct nk_window *win;
19442  struct nk_panel *layout;
19443 
19444  NK_ASSERT(ctx);
19445  NK_ASSERT(ctx->current);
19446  NK_ASSERT(ctx->current->layout);
19447  win = ctx->current;
19448  layout = win->layout;
19449 
19450  ret.x += -layout->at_x + (float)*layout->offset_x;
19451  ret.y += -layout->at_y + (float)*layout->offset_y;
19452  return ret;
19453 }
19454 
19455 NK_INTERN void
19456 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
19457 {
19458  struct nk_panel *layout = win->layout;
19459  struct nk_vec2 spacing = ctx->style.window.spacing;
19460  const float row_height = layout->row.height - spacing.y;
19461  nk_panel_layout(ctx, win, row_height, layout->row.columns);
19462 }
19463 
19464 NK_INTERN void
19465 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
19466  struct nk_window *win, int modify)
19467 {
19468  struct nk_panel *layout;
19469  const struct nk_style *style;
19470 
19471  struct nk_vec2 spacing;
19472  struct nk_vec2 padding;
19473 
19474  float item_offset = 0;
19475  float item_width = 0;
19476  float item_spacing = 0;
19477  float panel_space = 0;
19478 
19479  NK_ASSERT(ctx);
19480  NK_ASSERT(ctx->current);
19481  NK_ASSERT(ctx->current->layout);
19482  if (!ctx || !ctx->current || !ctx->current->layout)
19483  return;
19484 
19485  win = ctx->current;
19486  layout = win->layout;
19487  style = &ctx->style;
19488  NK_ASSERT(bounds);
19489 
19490  spacing = style->window.spacing;
19491  padding = nk_panel_get_padding(style, layout->type);
19492  panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19493  layout->bounds.w, layout->row.columns);
19494 
19495  /* calculate the width of one item inside the current layout space */
19496  switch (layout->row.type) {
19497  case NK_LAYOUT_DYNAMIC_FIXED: {
19498  /* scaling fixed size widgets item width */
19499  item_width = NK_MAX(1.0f,panel_space-1.0f) / (float)layout->row.columns;
19500  item_offset = (float)layout->row.index * item_width;
19501  item_spacing = (float)layout->row.index * spacing.x;
19502  } break;
19503  case NK_LAYOUT_DYNAMIC_ROW: {
19504  /* scaling single ratio widget width */
19505  item_width = layout->row.item_width * panel_space;
19506  item_offset = layout->row.item_offset;
19507  item_spacing = 0;
19508 
19509  if (modify) {
19510  layout->row.item_offset += item_width + spacing.x;
19511  layout->row.filled += layout->row.item_width;
19512  layout->row.index = 0;
19513  }
19514  } break;
19515  case NK_LAYOUT_DYNAMIC_FREE: {
19516  /* panel width depended free widget placing */
19517  bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
19518  bounds->x -= (float)*layout->offset_x;
19519  bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
19520  bounds->y -= (float)*layout->offset_y;
19521  bounds->w = layout->bounds.w * layout->row.item.w;
19522  bounds->h = layout->row.height * layout->row.item.h;
19523  return;
19524  } break;
19525  case NK_LAYOUT_DYNAMIC: {
19526  /* scaling arrays of panel width ratios for every widget */
19527  float ratio;
19528  NK_ASSERT(layout->row.ratio);
19529  ratio = (layout->row.ratio[layout->row.index] < 0) ?
19530  layout->row.item_width : layout->row.ratio[layout->row.index];
19531 
19532  item_spacing = (float)layout->row.index * spacing.x;
19533  item_width = (ratio * panel_space);
19534  item_offset = layout->row.item_offset;
19535 
19536  if (modify) {
19537  layout->row.item_offset += item_width;
19538  layout->row.filled += ratio;
19539  }
19540  } break;
19541  case NK_LAYOUT_STATIC_FIXED: {
19542  /* non-scaling fixed widgets item width */
19543  item_width = layout->row.item_width;
19544  item_offset = (float)layout->row.index * item_width;
19545  item_spacing = (float)layout->row.index * spacing.x;
19546  } break;
19547  case NK_LAYOUT_STATIC_ROW: {
19548  /* scaling single ratio widget width */
19549  item_width = layout->row.item_width;
19550  item_offset = layout->row.item_offset;
19551  item_spacing = (float)layout->row.index * spacing.x;
19552  if (modify) layout->row.item_offset += item_width;
19553  } break;
19554  case NK_LAYOUT_STATIC_FREE: {
19555  /* free widget placing */
19556  bounds->x = layout->at_x + layout->row.item.x;
19557  bounds->w = layout->row.item.w;
19558  if (((bounds->x + bounds->w) > layout->max_x) && modify)
19559  layout->max_x = (bounds->x + bounds->w);
19560  bounds->x -= (float)*layout->offset_x;
19561  bounds->y = layout->at_y + layout->row.item.y;
19562  bounds->y -= (float)*layout->offset_y;
19563  bounds->h = layout->row.item.h;
19564  return;
19565  } break;
19566  case NK_LAYOUT_STATIC: {
19567  /* non-scaling array of panel pixel width for every widget */
19568  item_spacing = (float)layout->row.index * spacing.x;
19569  item_width = layout->row.ratio[layout->row.index];
19570  item_offset = layout->row.item_offset;
19571  if (modify) layout->row.item_offset += item_width;
19572  } break;
19573  case NK_LAYOUT_TEMPLATE: {
19574  /* stretchy row layout with combined dynamic/static widget width*/
19575  NK_ASSERT(layout->row.index < layout->row.columns);
19576  NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19577  item_width = layout->row.templates[layout->row.index];
19578  item_offset = layout->row.item_offset;
19579  item_spacing = (float)layout->row.index * spacing.x;
19580  if (modify) layout->row.item_offset += item_width;
19581  } break;
19582  default: NK_ASSERT(0); break;
19583  };
19584 
19585  /* set the bounds of the newly allocated widget */
19586  bounds->w = item_width;
19587  bounds->h = layout->row.height - spacing.y;
19588  bounds->y = layout->at_y - (float)*layout->offset_y;
19589  bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
19590  if (((bounds->x + bounds->w) > layout->max_x) && modify)
19591  layout->max_x = bounds->x + bounds->w;
19592  bounds->x -= (float)*layout->offset_x;
19593 }
19594 
19595 NK_INTERN void
19596 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
19597 {
19598  struct nk_window *win;
19599  struct nk_panel *layout;
19600 
19601  NK_ASSERT(ctx);
19602  NK_ASSERT(ctx->current);
19603  NK_ASSERT(ctx->current->layout);
19604  if (!ctx || !ctx->current || !ctx->current->layout)
19605  return;
19606 
19607  /* check if the end of the row has been hit and begin new row if so */
19608  win = ctx->current;
19609  layout = win->layout;
19610  if (layout->row.index >= layout->row.columns)
19611  nk_panel_alloc_row(ctx, win);
19612 
19613  /* calculate widget position and size */
19614  nk_layout_widget_space(bounds, ctx, win, nk_true);
19615  layout->row.index++;
19616 }
19617 
19618 NK_INTERN void
19619 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
19620 {
19621  float y;
19622  int index;
19623  struct nk_window *win;
19624  struct nk_panel *layout;
19625 
19626  NK_ASSERT(ctx);
19627  NK_ASSERT(ctx->current);
19628  NK_ASSERT(ctx->current->layout);
19629  if (!ctx || !ctx->current || !ctx->current->layout)
19630  return;
19631 
19632  win = ctx->current;
19633  layout = win->layout;
19634  y = layout->at_y;
19635  index = layout->row.index;
19636  if (layout->row.index >= layout->row.columns) {
19637  layout->at_y += layout->row.height;
19638  layout->row.index = 0;
19639  }
19640  nk_layout_widget_space(bounds, ctx, win, nk_false);
19641  layout->at_y = y;
19642  layout->row.index = index;
19643 }
19644 
19645 NK_INTERN int
19646 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
19647  struct nk_image *img, const char *title, enum nk_collapse_states *state)
19648 {
19649  struct nk_window *win;
19650  struct nk_panel *layout;
19651  const struct nk_style *style;
19652  struct nk_command_buffer *out;
19653  const struct nk_input *in;
19654  const struct nk_style_button *button;
19655  enum nk_symbol_type symbol;
19656 
19657  struct nk_vec2 item_spacing;
19658  struct nk_rect header = {0,0,0,0};
19659  struct nk_rect sym = {0,0,0,0};
19660  struct nk_text text;
19661 
19662  nk_flags ws = 0;
19663  enum nk_widget_layout_states widget_state;
19664 
19665  NK_ASSERT(ctx);
19666  NK_ASSERT(ctx->current);
19667  NK_ASSERT(ctx->current->layout);
19668  if (!ctx || !ctx->current || !ctx->current->layout)
19669  return 0;
19670 
19671  /* cache some data */
19672  win = ctx->current;
19673  layout = win->layout;
19674  out = &win->buffer;
19675  style = &ctx->style;
19676  item_spacing = style->window.spacing;
19677 
19678  /* calculate header bounds and draw background */
19679  nk_layout_row_dynamic(ctx, style->font->height + 2 * style->tab.padding.y, 1);
19680  widget_state = nk_widget(&header, ctx);
19681  if (type == NK_TREE_TAB) {
19682  const struct nk_style_item *background = &style->tab.background;
19683  if (background->type == NK_STYLE_ITEM_IMAGE) {
19684  nk_draw_image(out, header, &background->data.image, nk_white);
19685  text.background = nk_rgba(0,0,0,0);
19686  } else {
19687  text.background = background->data.color;
19688  nk_fill_rect(out, header, 0, style->tab.border_color);
19689  nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
19690  style->tab.rounding, background->data.color);
19691  }
19692  } else text.background = style->window.background;
19693 
19694  /* update node state */
19695  in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
19696  in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
19697  if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
19698  *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
19699 
19700  /* select correct button style */
19701  if (*state == NK_MAXIMIZED) {
19702  symbol = style->tab.sym_maximize;
19703  if (type == NK_TREE_TAB)
19704  button = &style->tab.tab_maximize_button;
19705  else button = &style->tab.node_maximize_button;
19706  } else {
19707  symbol = style->tab.sym_minimize;
19708  if (type == NK_TREE_TAB)
19709  button = &style->tab.tab_minimize_button;
19710  else button = &style->tab.node_minimize_button;
19711  }
19712 
19713  {/* draw triangle button */
19714  sym.w = sym.h = style->font->height;
19715  sym.y = header.y + style->tab.padding.y;
19716  sym.x = header.x + style->tab.padding.x;
19717  nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
19718  button, 0, style->font);
19719 
19720  if (img) {
19721  /* draw optional image icon */
19722  sym.x = sym.x + sym.w + 4 * item_spacing.x;
19723  nk_draw_image(&win->buffer, sym, img, nk_white);
19724  sym.w = style->font->height + style->tab.spacing.x;}
19725  }
19726 
19727  {/* draw label */
19728  struct nk_rect label;
19729  header.w = NK_MAX(header.w, sym.w + item_spacing.x);
19730  label.x = sym.x + sym.w + item_spacing.x;
19731  label.y = sym.y;
19732  label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
19733  label.h = style->font->height;
19734  text.text = style->tab.text;
19735  text.padding = nk_vec2(0,0);
19736  nk_widget_text(out, label, title, nk_strlen(title), &text,
19737  NK_TEXT_LEFT, style->font);}
19738 
19739  /* increase x-axis cursor widget position pointer */
19740  if (*state == NK_MAXIMIZED) {
19741  layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
19742  layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
19743  layout->bounds.w -= (style->tab.indent + style->window.padding.x);
19744  layout->row.tree_depth++;
19745  return nk_true;
19746  } else return nk_false;
19747 }
19748 
19749 NK_INTERN int
19750 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
19751  struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
19752  const char *hash, int len, int line)
19753 {
19754  struct nk_window *win = ctx->current;
19755  int title_len = 0;
19756  nk_hash tree_hash = 0;
19757  nk_uint *state = 0;
19758 
19759  /* retrieve tree state from internal widget state tables */
19760  if (!hash) {
19761  title_len = (int)nk_strlen(title);
19762  tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
19763  } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
19764  state = nk_find_value(win, tree_hash);
19765  if (!state) {
19766  state = nk_add_value(ctx, win, tree_hash, 0);
19767  *state = initial_state;
19768  }
19769  return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
19770 }
19771 
19772 NK_API int
19773 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
19774  const char *title, enum nk_collapse_states *state)
19775 {return nk_tree_state_base(ctx, type, 0, title, state);}
19776 
19777 NK_API int
19778 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
19779  struct nk_image img, const char *title, enum nk_collapse_states *state)
19780 {return nk_tree_state_base(ctx, type, &img, title, state);}
19781 
19782 NK_API void
19783 nk_tree_state_pop(struct nk_context *ctx)
19784 {
19785  struct nk_window *win = 0;
19786  struct nk_panel *layout = 0;
19787 
19788  NK_ASSERT(ctx);
19789  NK_ASSERT(ctx->current);
19790  NK_ASSERT(ctx->current->layout);
19791  if (!ctx || !ctx->current || !ctx->current->layout)
19792  return;
19793 
19794  win = ctx->current;
19795  layout = win->layout;
19796  layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
19797  layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
19798  NK_ASSERT(layout->row.tree_depth);
19799  layout->row.tree_depth--;
19800 }
19801 
19802 NK_API int
19803 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
19804  const char *title, enum nk_collapse_states initial_state,
19805  const char *hash, int len, int line)
19806 {return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);}
19807 
19808 NK_API int
19809 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
19810  struct nk_image img, const char *title, enum nk_collapse_states initial_state,
19811  const char *hash, int len,int seed)
19812 {return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);}
19813 
19814 NK_API void
19815 nk_tree_pop(struct nk_context *ctx)
19816 {nk_tree_state_pop(ctx);}
19817 
19818 /*----------------------------------------------------------------
19819  *
19820  * WIDGETS
19821  *
19822  * --------------------------------------------------------------*/
19823 NK_API struct nk_rect
19825 {
19826  struct nk_rect bounds;
19827  NK_ASSERT(ctx);
19828  NK_ASSERT(ctx->current);
19829  if (!ctx || !ctx->current)
19830  return nk_rect(0,0,0,0);
19831  nk_layout_peek(&bounds, ctx);
19832  return bounds;
19833 }
19834 
19835 NK_API struct nk_vec2
19837 {
19838  struct nk_rect bounds;
19839  NK_ASSERT(ctx);
19840  NK_ASSERT(ctx->current);
19841  if (!ctx || !ctx->current)
19842  return nk_vec2(0,0);
19843 
19844  nk_layout_peek(&bounds, ctx);
19845  return nk_vec2(bounds.x, bounds.y);
19846 }
19847 
19848 NK_API struct nk_vec2
19849 nk_widget_size(struct nk_context *ctx)
19850 {
19851  struct nk_rect bounds;
19852  NK_ASSERT(ctx);
19853  NK_ASSERT(ctx->current);
19854  if (!ctx || !ctx->current)
19855  return nk_vec2(0,0);
19856 
19857  nk_layout_peek(&bounds, ctx);
19858  return nk_vec2(bounds.w, bounds.h);
19859 }
19860 
19861 NK_API float
19862 nk_widget_width(struct nk_context *ctx)
19863 {
19864  struct nk_rect bounds;
19865  NK_ASSERT(ctx);
19866  NK_ASSERT(ctx->current);
19867  if (!ctx || !ctx->current)
19868  return 0;
19869 
19870  nk_layout_peek(&bounds, ctx);
19871  return bounds.w;
19872 }
19873 
19874 NK_API float
19875 nk_widget_height(struct nk_context *ctx)
19876 {
19877  struct nk_rect bounds;
19878  NK_ASSERT(ctx);
19879  NK_ASSERT(ctx->current);
19880  if (!ctx || !ctx->current)
19881  return 0;
19882 
19883  nk_layout_peek(&bounds, ctx);
19884  return bounds.h;
19885 }
19886 
19887 NK_API int
19888 nk_widget_is_hovered(struct nk_context *ctx)
19889 {
19890  int ret;
19891  struct nk_rect bounds;
19892  NK_ASSERT(ctx);
19893  NK_ASSERT(ctx->current);
19894  if (!ctx || !ctx->current)
19895  return 0;
19896 
19897  nk_layout_peek(&bounds, ctx);
19898  ret = (ctx->active == ctx->current);
19899  ret = ret && nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
19900  return ret;
19901 }
19902 
19903 NK_API int
19904 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
19905 {
19906  int ret;
19907  struct nk_rect bounds;
19908  NK_ASSERT(ctx);
19909  NK_ASSERT(ctx->current);
19910  if (!ctx || !ctx->current)
19911  return 0;
19912 
19913  nk_layout_peek(&bounds, ctx);
19914  ret = (ctx->active == ctx->current);
19915  ret = ret && nk_input_mouse_clicked(&ctx->input, btn, bounds);
19916  return ret;
19917 }
19918 
19919 NK_API int
19920 nk_widget_is_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
19921 {
19922  int ret;
19923  struct nk_rect bounds;
19924  NK_ASSERT(ctx);
19925  NK_ASSERT(ctx->current);
19926  if (!ctx || !ctx->current)
19927  return 0;
19928 
19929  nk_layout_peek(&bounds, ctx);
19930  ret = (ctx->active == ctx->current);
19931  ret = ret && nk_input_is_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
19932  return ret;
19933 }
19934 
19935 NK_API int
19936 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
19937 {
19938  int ret;
19939  struct nk_rect bounds;
19940  NK_ASSERT(ctx);
19941  NK_ASSERT(ctx->current);
19942  if (!ctx || !ctx->current)
19943  return 0;
19944 
19945  nk_layout_peek(&bounds, ctx);
19946  ret = (ctx->active == ctx->current);
19947  ret = ret && nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
19948  return ret;
19949 }
19950 
19952 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
19953 {
19954  struct nk_rect c;
19955  struct nk_window *win;
19956  struct nk_panel *layout;
19957 
19958  NK_ASSERT(ctx);
19959  NK_ASSERT(ctx->current);
19960  NK_ASSERT(ctx->current->layout);
19961  if (!ctx || !ctx->current || !ctx->current->layout)
19962  return NK_WIDGET_INVALID;
19963 
19964  /* allocate space and check if the widget needs to be updated and drawn */
19965  nk_panel_alloc_space(bounds, ctx);
19966  win = ctx->current;
19967  layout = win->layout;
19968  c = layout->clip;
19969 
19970  /* if one of these triggers you forgot to add an `if` condition around either
19971  a window, group, popup, combobox or contextual menu `begin` and `end` block.
19972  Example:
19973  if (nk_begin(...) {...} nk_end(...); or
19974  if (nk_group_begin(...) { nk_group_end(...);} */
19975  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
19976  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
19977  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
19978 
19979  /* need to convert to int here to remove floating point errors */
19980  bounds->x = (float)((int)bounds->x);
19981  bounds->y = (float)((int)bounds->y);
19982  bounds->w = (float)((int)bounds->w);
19983  bounds->h = (float)((int)bounds->h);
19984 
19985  c.x = (float)((int)c.x);
19986  c.y = (float)((int)c.y);
19987  c.w = (float)((int)c.w);
19988  c.h = (float)((int)c.h);
19989 
19990  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
19991  return NK_WIDGET_INVALID;
19992  if (!NK_CONTAINS(bounds->x, bounds->y, bounds->w, bounds->h, c.x, c.y, c.w, c.h))
19993  return NK_WIDGET_ROM;
19994  return NK_WIDGET_VALID;
19995 }
19996 
19998 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
19999  struct nk_vec2 item_padding)
20000 {
20001  /* update the bounds to stand without padding */
20002  struct nk_window *win;
20003  struct nk_style *style;
20004  struct nk_panel *layout;
20005  enum nk_widget_layout_states state;
20006  struct nk_vec2 panel_padding;
20007 
20008  NK_ASSERT(ctx);
20009  NK_ASSERT(ctx->current);
20010  NK_ASSERT(ctx->current->layout);
20011  if (!ctx || !ctx->current || !ctx->current->layout)
20012  return NK_WIDGET_INVALID;
20013 
20014  win = ctx->current;
20015  style = &ctx->style;
20016  layout = win->layout;
20017  state = nk_widget(bounds, ctx);
20018 
20019  panel_padding = nk_panel_get_padding(style, layout->type);
20020  if (layout->row.index == 1) {
20021  bounds->w += panel_padding.x;
20022  bounds->x -= panel_padding.x;
20023  } else bounds->x -= item_padding.x;
20024 
20025  if (layout->row.index == layout->row.columns)
20026  bounds->w += panel_padding.x;
20027  else bounds->w += item_padding.x;
20028  return state;
20029 }
20030 
20031 /*----------------------------------------------------------------
20032  *
20033  * MISC
20034  *
20035  * --------------------------------------------------------------*/
20036 NK_API void
20037 nk_spacing(struct nk_context *ctx, int cols)
20038 {
20039  struct nk_window *win;
20040  struct nk_panel *layout;
20041  struct nk_rect none;
20042  int i, index, rows;
20043 
20044  NK_ASSERT(ctx);
20045  NK_ASSERT(ctx->current);
20046  NK_ASSERT(ctx->current->layout);
20047  if (!ctx || !ctx->current || !ctx->current->layout)
20048  return;
20049 
20050  /* spacing over row boundaries */
20051  win = ctx->current;
20052  layout = win->layout;
20053  index = (layout->row.index + cols) % layout->row.columns;
20054  rows = (layout->row.index + cols) / layout->row.columns;
20055  if (rows) {
20056  for (i = 0; i < rows; ++i)
20057  nk_panel_alloc_row(ctx, win);
20058  cols = index;
20059  }
20060 
20061  /* non table layout need to allocate space */
20062  if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
20063  layout->row.type != NK_LAYOUT_STATIC_FIXED) {
20064  for (i = 0; i < cols; ++i)
20065  nk_panel_alloc_space(&none, ctx);
20066  }
20067  layout->row.index = index;
20068 }
20069 
20070 /*----------------------------------------------------------------
20071  *
20072  * TEXT
20073  *
20074  * --------------------------------------------------------------*/
20075 NK_API void
20076 nk_text_colored(struct nk_context *ctx, const char *str, int len,
20077  nk_flags alignment, struct nk_color color)
20078 {
20079  struct nk_window *win;
20080  const struct nk_style *style;
20081 
20082  struct nk_vec2 item_padding;
20083  struct nk_rect bounds;
20084  struct nk_text text;
20085 
20086  NK_ASSERT(ctx);
20087  NK_ASSERT(ctx->current);
20088  NK_ASSERT(ctx->current->layout);
20089  if (!ctx || !ctx->current || !ctx->current->layout) return;
20090 
20091  win = ctx->current;
20092  style = &ctx->style;
20093  nk_panel_alloc_space(&bounds, ctx);
20094  item_padding = style->text.padding;
20095 
20096  text.padding.x = item_padding.x;
20097  text.padding.y = item_padding.y;
20098  text.background = style->window.background;
20099  text.text = color;
20100  nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
20101 }
20102 
20103 NK_API void
20104 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
20105  int len, struct nk_color color)
20106 {
20107  struct nk_window *win;
20108  const struct nk_style *style;
20109 
20110  struct nk_vec2 item_padding;
20111  struct nk_rect bounds;
20112  struct nk_text text;
20113 
20114  NK_ASSERT(ctx);
20115  NK_ASSERT(ctx->current);
20116  NK_ASSERT(ctx->current->layout);
20117  if (!ctx || !ctx->current || !ctx->current->layout) return;
20118 
20119  win = ctx->current;
20120  style = &ctx->style;
20121  nk_panel_alloc_space(&bounds, ctx);
20122  item_padding = style->text.padding;
20123 
20124  text.padding.x = item_padding.x;
20125  text.padding.y = item_padding.y;
20126  text.background = style->window.background;
20127  text.text = color;
20128  nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
20129 }
20130 
20131 #ifdef NK_INCLUDE_STANDARD_VARARGS
20132 NK_API void
20133 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
20134  struct nk_color color, const char *fmt, ...)
20135 {
20136  char buf[256];
20137  va_list args;
20138  va_start(args, fmt);
20139  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20140  nk_label_colored(ctx, buf, flags, color);
20141  va_end(args);
20142 }
20143 
20144 NK_API void
20145 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
20146  const char *fmt, ...)
20147 {
20148  char buf[256];
20149  va_list args;
20150  va_start(args, fmt);
20151  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20152  nk_label_colored_wrap(ctx, buf, color);
20153  va_end(args);
20154 }
20155 
20156 NK_API void
20157 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
20158 {
20159  char buf[256];
20160  va_list args;
20161  va_start(args, fmt);
20162  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20163  nk_label(ctx, buf, flags);
20164  va_end(args);
20165 }
20166 
20167 NK_API void
20168 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
20169 {
20170  char buf[256];
20171  va_list args;
20172  va_start(args, fmt);
20173  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20174  nk_label_wrap(ctx, buf);
20175  va_end(args);
20176 }
20177 
20178 NK_API void
20179 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
20180 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));}
20181 
20182 NK_API void
20183 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
20184 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);}
20185 
20186 NK_API void
20187 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
20188 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);}
20189 
20190 NK_API void
20191 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
20192 {
20193  double double_value = (double)value;
20194  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
20195 }
20196 
20197 NK_API void
20198 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
20199 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);}
20200 
20201 NK_API void
20202 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
20203 {
20204  double c[4]; nk_color_dv(c, color);
20205  nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
20206  p, c[0], c[1], c[2], c[3]);
20207 }
20208 
20209 NK_API void
20210 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
20211 {
20212  char hex[16];
20213  nk_color_hex_rgba(hex, color);
20214  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
20215 }
20216 #endif
20217 
20218 NK_API void
20219 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
20220 {
20221  NK_ASSERT(ctx);
20222  if (!ctx) return;
20223  nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
20224 }
20225 
20226 NK_API void
20227 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
20228 {
20229  NK_ASSERT(ctx);
20230  if (!ctx) return;
20231  nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
20232 }
20233 
20234 NK_API void
20235 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
20236 {nk_text(ctx, str, nk_strlen(str), alignment);}
20237 
20238 NK_API void
20239 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
20240  struct nk_color color)
20241 {nk_text_colored(ctx, str, nk_strlen(str), align, color);}
20242 
20243 NK_API void
20244 nk_label_wrap(struct nk_context *ctx, const char *str)
20245 {nk_text_wrap(ctx, str, nk_strlen(str));}
20246 
20247 NK_API void
20248 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
20249 {nk_text_wrap_colored(ctx, str, nk_strlen(str), color);}
20250 
20251 NK_API void
20252 nk_image(struct nk_context *ctx, struct nk_image img)
20253 {
20254  struct nk_window *win;
20255  struct nk_rect bounds;
20256 
20257  NK_ASSERT(ctx);
20258  NK_ASSERT(ctx->current);
20259  NK_ASSERT(ctx->current->layout);
20260  if (!ctx || !ctx->current || !ctx->current->layout) return;
20261 
20262  win = ctx->current;
20263  if (!nk_widget(&bounds, ctx)) return;
20264  nk_draw_image(&win->buffer, bounds, &img, nk_white);
20265 }
20266 
20267 /*----------------------------------------------------------------
20268  *
20269  * BUTTON
20270  *
20271  * --------------------------------------------------------------*/
20272 NK_API void
20273 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20274 {
20275  NK_ASSERT(ctx);
20276  if (!ctx) return;
20277  ctx->button_behavior = behavior;
20278 }
20279 
20280 NK_API int
20281 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20282 {
20283  struct nk_config_stack_button_behavior *button_stack;
20284  struct nk_config_stack_button_behavior_element *element;
20285 
20286  NK_ASSERT(ctx);
20287  if (!ctx) return 0;
20288 
20289  button_stack = &ctx->stacks.button_behaviors;
20290  NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
20291  if (button_stack->head >= (int)NK_LEN(button_stack->elements))
20292  return 0;
20293 
20294  element = &button_stack->elements[button_stack->head++];
20295  element->address = &ctx->button_behavior;
20296  element->old_value = ctx->button_behavior;
20297  ctx->button_behavior = behavior;
20298  return 1;
20299 }
20300 
20301 NK_API int
20303 {
20304  struct nk_config_stack_button_behavior *button_stack;
20305  struct nk_config_stack_button_behavior_element *element;
20306 
20307  NK_ASSERT(ctx);
20308  if (!ctx) return 0;
20309 
20310  button_stack = &ctx->stacks.button_behaviors;
20311  NK_ASSERT(button_stack->head > 0);
20312  if (button_stack->head < 1)
20313  return 0;
20314 
20315  element = &button_stack->elements[--button_stack->head];
20316  *element->address = element->old_value;
20317  return 1;
20318 }
20319 
20320 NK_API int
20321 nk_button_text_styled(struct nk_context *ctx,
20322  const struct nk_style_button *style, const char *title, int len)
20323 {
20324  struct nk_window *win;
20325  struct nk_panel *layout;
20326  const struct nk_input *in;
20327 
20328  struct nk_rect bounds;
20329  enum nk_widget_layout_states state;
20330 
20331  NK_ASSERT(ctx);
20332  NK_ASSERT(style);
20333  NK_ASSERT(ctx->current);
20334  NK_ASSERT(ctx->current->layout);
20335  if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
20336 
20337  win = ctx->current;
20338  layout = win->layout;
20339  state = nk_widget(&bounds, ctx);
20340 
20341  if (!state) return 0;
20342  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20343  return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
20344  title, len, style->text_alignment, ctx->button_behavior,
20345  style, in, ctx->style.font);
20346 }
20347 
20348 NK_API int
20349 nk_button_text(struct nk_context *ctx, const char *title, int len)
20350 {
20351  NK_ASSERT(ctx);
20352  if (!ctx) return 0;
20353  return nk_button_text_styled(ctx, &ctx->style.button, title, len);
20354 }
20355 
20356 NK_API int nk_button_label_styled(struct nk_context *ctx,
20357  const struct nk_style_button *style, const char *title)
20358 {return nk_button_text_styled(ctx, style, title, nk_strlen(title));}
20359 
20360 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
20361 {return nk_button_text(ctx, title, nk_strlen(title));}
20362 
20363 NK_API int
20364 nk_button_color(struct nk_context *ctx, struct nk_color color)
20365 {
20366  struct nk_window *win;
20367  struct nk_panel *layout;
20368  const struct nk_input *in;
20369  struct nk_style_button button;
20370 
20371  int ret = 0;
20372  struct nk_rect bounds;
20373  struct nk_rect content;
20374  enum nk_widget_layout_states state;
20375 
20376  NK_ASSERT(ctx);
20377  NK_ASSERT(ctx->current);
20378  NK_ASSERT(ctx->current->layout);
20379  if (!ctx || !ctx->current || !ctx->current->layout)
20380  return 0;
20381 
20382  win = ctx->current;
20383  layout = win->layout;
20384 
20385  state = nk_widget(&bounds, ctx);
20386  if (!state) return 0;
20387  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20388 
20389  button = ctx->style.button;
20390  button.normal = nk_style_item_color(color);
20391  button.hover = nk_style_item_color(color);
20392  button.active = nk_style_item_color(color);
20393  ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
20394  &button, in, ctx->button_behavior, &content);
20395  nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
20396  return ret;
20397 }
20398 
20399 NK_API int
20401  const struct nk_style_button *style, enum nk_symbol_type symbol)
20402 {
20403  struct nk_window *win;
20404  struct nk_panel *layout;
20405  const struct nk_input *in;
20406 
20407  struct nk_rect bounds;
20408  enum nk_widget_layout_states state;
20409 
20410  NK_ASSERT(ctx);
20411  NK_ASSERT(ctx->current);
20412  NK_ASSERT(ctx->current->layout);
20413  if (!ctx || !ctx->current || !ctx->current->layout)
20414  return 0;
20415 
20416  win = ctx->current;
20417  layout = win->layout;
20418  state = nk_widget(&bounds, ctx);
20419  if (!state) return 0;
20420  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20421  return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20422  symbol, ctx->button_behavior, style, in, ctx->style.font);
20423 }
20424 
20425 NK_API int
20426 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
20427 {
20428  NK_ASSERT(ctx);
20429  if (!ctx) return 0;
20430  return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
20431 }
20432 
20433 NK_API int
20434 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
20435  struct nk_image img)
20436 {
20437  struct nk_window *win;
20438  struct nk_panel *layout;
20439  const struct nk_input *in;
20440 
20441  struct nk_rect bounds;
20442  enum nk_widget_layout_states state;
20443 
20444  NK_ASSERT(ctx);
20445  NK_ASSERT(ctx->current);
20446  NK_ASSERT(ctx->current->layout);
20447  if (!ctx || !ctx->current || !ctx->current->layout)
20448  return 0;
20449 
20450  win = ctx->current;
20451  layout = win->layout;
20452 
20453  state = nk_widget(&bounds, ctx);
20454  if (!state) return 0;
20455  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20456  return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
20457  img, ctx->button_behavior, style, in);
20458 }
20459 
20460 NK_API int
20461 nk_button_image(struct nk_context *ctx, struct nk_image img)
20462 {
20463  NK_ASSERT(ctx);
20464  if (!ctx) return 0;
20465  return nk_button_image_styled(ctx, &ctx->style.button, img);
20466 }
20467 
20468 NK_API int
20470  const struct nk_style_button *style, enum nk_symbol_type symbol,
20471  const char *text, int len, nk_flags align)
20472 {
20473  struct nk_window *win;
20474  struct nk_panel *layout;
20475  const struct nk_input *in;
20476 
20477  struct nk_rect bounds;
20478  enum nk_widget_layout_states state;
20479 
20480  NK_ASSERT(ctx);
20481  NK_ASSERT(ctx->current);
20482  NK_ASSERT(ctx->current->layout);
20483  if (!ctx || !ctx->current || !ctx->current->layout)
20484  return 0;
20485 
20486  win = ctx->current;
20487  layout = win->layout;
20488 
20489  state = nk_widget(&bounds, ctx);
20490  if (!state) return 0;
20491  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20492  return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20493  symbol, text, len, align, ctx->button_behavior,
20494  style, ctx->style.font, in);
20495 }
20496 
20497 NK_API int
20498 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
20499  const char* text, int len, nk_flags align)
20500 {
20501  NK_ASSERT(ctx);
20502  if (!ctx) return 0;
20503  return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
20504 }
20505 
20506 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
20507  const char *label, nk_flags align)
20508 {return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);}
20509 
20511  const struct nk_style_button *style, enum nk_symbol_type symbol,
20512  const char *title, nk_flags align)
20513 {return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);}
20514 
20515 NK_API int
20517  const struct nk_style_button *style, struct nk_image img, const char *text,
20518  int len, nk_flags align)
20519 {
20520  struct nk_window *win;
20521  struct nk_panel *layout;
20522  const struct nk_input *in;
20523 
20524  struct nk_rect bounds;
20525  enum nk_widget_layout_states state;
20526 
20527  NK_ASSERT(ctx);
20528  NK_ASSERT(ctx->current);
20529  NK_ASSERT(ctx->current->layout);
20530  if (!ctx || !ctx->current || !ctx->current->layout)
20531  return 0;
20532 
20533  win = ctx->current;
20534  layout = win->layout;
20535 
20536  state = nk_widget(&bounds, ctx);
20537  if (!state) return 0;
20538  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20539  return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
20540  bounds, img, text, len, align, ctx->button_behavior,
20541  style, ctx->style.font, in);
20542 }
20543 
20544 NK_API int
20545 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
20546  const char *text, int len, nk_flags align)
20547 {return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);}
20548 
20549 
20550 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
20551  const char *label, nk_flags align)
20552 {return nk_button_image_text(ctx, img, label, nk_strlen(label), align);}
20553 
20555  const struct nk_style_button *style, struct nk_image img,
20556  const char *label, nk_flags text_alignment)
20557 {return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);}
20558 
20559 /*----------------------------------------------------------------
20560  *
20561  * SELECTABLE
20562  *
20563  * --------------------------------------------------------------*/
20564 NK_API int
20565 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
20566  nk_flags align, int *value)
20567 {
20568  struct nk_window *win;
20569  struct nk_panel *layout;
20570  const struct nk_input *in;
20571  const struct nk_style *style;
20572 
20573  enum nk_widget_layout_states state;
20574  struct nk_rect bounds;
20575 
20576  NK_ASSERT(ctx);
20577  NK_ASSERT(value);
20578  NK_ASSERT(ctx->current);
20579  NK_ASSERT(ctx->current->layout);
20580  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20581  return 0;
20582 
20583  win = ctx->current;
20584  layout = win->layout;
20585  style = &ctx->style;
20586 
20587  state = nk_widget(&bounds, ctx);
20588  if (!state) return 0;
20589  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20590  return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
20591  str, len, align, value, &style->selectable, in, style->font);
20592 }
20593 
20594 NK_API int
20595 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
20596  const char *str, int len, nk_flags align, int *value)
20597 {
20598  struct nk_window *win;
20599  struct nk_panel *layout;
20600  const struct nk_input *in;
20601  const struct nk_style *style;
20602 
20603  enum nk_widget_layout_states state;
20604  struct nk_rect bounds;
20605 
20606  NK_ASSERT(ctx);
20607  NK_ASSERT(value);
20608  NK_ASSERT(ctx->current);
20609  NK_ASSERT(ctx->current->layout);
20610  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20611  return 0;
20612 
20613  win = ctx->current;
20614  layout = win->layout;
20615  style = &ctx->style;
20616 
20617  state = nk_widget(&bounds, ctx);
20618  if (!state) return 0;
20619  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20620  return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
20621  str, len, align, value, &img, &style->selectable, in, style->font);
20622 }
20623 
20624 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
20625  nk_flags align, int value)
20626 {nk_selectable_text(ctx, str, len, align, &value);return value;}
20627 
20628 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
20629 {return nk_selectable_text(ctx, str, nk_strlen(str), align, value);}
20630 
20631 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
20632  const char *str, nk_flags align, int *value)
20633 {return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);}
20634 
20635 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
20636 {nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;}
20637 
20638 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
20639  const char *str, nk_flags align, int value)
20640 {nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;}
20641 
20642 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
20643  const char *str, int len, nk_flags align, int value)
20644 {nk_selectable_image_text(ctx, img, str, len, align, &value);return value;}
20645 
20646 /*----------------------------------------------------------------
20647  *
20648  * CHECKBOX
20649  *
20650  * --------------------------------------------------------------*/
20651 NK_API int
20652 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
20653 {
20654  struct nk_window *win;
20655  struct nk_panel *layout;
20656  const struct nk_input *in;
20657  const struct nk_style *style;
20658 
20659  struct nk_rect bounds;
20660  enum nk_widget_layout_states state;
20661 
20662  NK_ASSERT(ctx);
20663  NK_ASSERT(ctx->current);
20664  NK_ASSERT(ctx->current->layout);
20665  if (!ctx || !ctx->current || !ctx->current->layout)
20666  return active;
20667 
20668  win = ctx->current;
20669  style = &ctx->style;
20670  layout = win->layout;
20671 
20672  state = nk_widget(&bounds, ctx);
20673  if (!state) return active;
20674  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20675  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
20676  text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
20677  return active;
20678 }
20679 
20680 NK_API unsigned int
20681 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
20682  unsigned int flags, unsigned int value)
20683 {
20684  int old_active;
20685  NK_ASSERT(ctx);
20686  NK_ASSERT(text);
20687  if (!ctx || !text) return flags;
20688  old_active = (int)((flags & value) & value);
20689  if (nk_check_text(ctx, text, len, old_active))
20690  flags |= value;
20691  else flags &= ~value;
20692  return flags;
20693 }
20694 
20695 NK_API int
20696 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
20697 {
20698  int old_val;
20699  NK_ASSERT(ctx);
20700  NK_ASSERT(text);
20701  NK_ASSERT(active);
20702  if (!ctx || !text || !active) return 0;
20703  old_val = *active;
20704  *active = nk_check_text(ctx, text, len, *active);
20705  return old_val != *active;
20706 }
20707 
20708 NK_API int
20709 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
20710  unsigned int *flags, unsigned int value)
20711 {
20712  int active;
20713  NK_ASSERT(ctx);
20714  NK_ASSERT(text);
20715  NK_ASSERT(flags);
20716  if (!ctx || !text || !flags) return 0;
20717 
20718  active = (int)((*flags & value) & value);
20719  if (nk_checkbox_text(ctx, text, len, &active)) {
20720  if (active) *flags |= value;
20721  else *flags &= ~value;
20722  return 1;
20723  }
20724  return 0;
20725 }
20726 
20727 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
20728 {return nk_check_text(ctx, label, nk_strlen(label), active);}
20729 
20730 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
20731  unsigned int flags, unsigned int value)
20732 {return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);}
20733 
20734 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
20735 {return nk_checkbox_text(ctx, label, nk_strlen(label), active);}
20736 
20737 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
20738  unsigned int *flags, unsigned int value)
20739 {return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);}
20740 
20741 /*----------------------------------------------------------------
20742  *
20743  * OPTION
20744  *
20745  * --------------------------------------------------------------*/
20746 NK_API int
20747 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
20748 {
20749  struct nk_window *win;
20750  struct nk_panel *layout;
20751  const struct nk_input *in;
20752  const struct nk_style *style;
20753 
20754  struct nk_rect bounds;
20755  enum nk_widget_layout_states state;
20756 
20757  NK_ASSERT(ctx);
20758  NK_ASSERT(ctx->current);
20759  NK_ASSERT(ctx->current->layout);
20760  if (!ctx || !ctx->current || !ctx->current->layout)
20761  return is_active;
20762 
20763  win = ctx->current;
20764  style = &ctx->style;
20765  layout = win->layout;
20766 
20767  state = nk_widget(&bounds, ctx);
20768  if (!state) return state;
20769  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20770  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
20771  text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
20772  return is_active;
20773 }
20774 
20775 NK_API int
20776 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
20777 {
20778  int old_value;
20779  NK_ASSERT(ctx);
20780  NK_ASSERT(text);
20781  NK_ASSERT(active);
20782  if (!ctx || !text || !active) return 0;
20783  old_value = *active;
20784  *active = nk_option_text(ctx, text, len, old_value);
20785  return old_value != *active;
20786 }
20787 
20788 NK_API int
20789 nk_option_label(struct nk_context *ctx, const char *label, int active)
20790 {return nk_option_text(ctx, label, nk_strlen(label), active);}
20791 
20792 NK_API int
20793 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
20794 {return nk_radio_text(ctx, label, nk_strlen(label), active);}
20795 
20796 /*----------------------------------------------------------------
20797  *
20798  * SLIDER
20799  *
20800  * --------------------------------------------------------------*/
20801 NK_API int
20802 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
20803  float value_step)
20804 {
20805  struct nk_window *win;
20806  struct nk_panel *layout;
20807  struct nk_input *in;
20808  const struct nk_style *style;
20809 
20810  int ret = 0;
20811  float old_value;
20812  struct nk_rect bounds;
20813  enum nk_widget_layout_states state;
20814 
20815  NK_ASSERT(ctx);
20816  NK_ASSERT(ctx->current);
20817  NK_ASSERT(ctx->current->layout);
20818  NK_ASSERT(value);
20819  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20820  return ret;
20821 
20822  win = ctx->current;
20823  style = &ctx->style;
20824  layout = win->layout;
20825 
20826  state = nk_widget(&bounds, ctx);
20827  if (!state) return ret;
20828  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20829 
20830  old_value = *value;
20831  *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
20832  old_value, max_value, value_step, &style->slider, in, style->font);
20833  return (old_value > *value || old_value < *value);
20834 }
20835 
20836 NK_API float
20837 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
20838 {
20839  nk_slider_float(ctx, min, &val, max, step); return val;
20840 }
20841 
20842 NK_API int
20843 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
20844 {
20845  float value = (float)val;
20846  nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
20847  return (int)value;
20848 }
20849 
20850 NK_API int
20851 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
20852 {
20853  int ret;
20854  float value = (float)*val;
20855  ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
20856  *val = (int)value;
20857  return ret;
20858 }
20859 
20860 /*----------------------------------------------------------------
20861  *
20862  * PROGRESSBAR
20863  *
20864  * --------------------------------------------------------------*/
20865 NK_API int
20866 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
20867 {
20868  struct nk_window *win;
20869  struct nk_panel *layout;
20870  const struct nk_style *style;
20871  const struct nk_input *in;
20872 
20873  struct nk_rect bounds;
20874  enum nk_widget_layout_states state;
20875  nk_size old_value;
20876 
20877  NK_ASSERT(ctx);
20878  NK_ASSERT(cur);
20879  NK_ASSERT(ctx->current);
20880  NK_ASSERT(ctx->current->layout);
20881  if (!ctx || !ctx->current || !ctx->current->layout || !cur)
20882  return 0;
20883 
20884  win = ctx->current;
20885  style = &ctx->style;
20886  layout = win->layout;
20887  state = nk_widget(&bounds, ctx);
20888  if (!state) return 0;
20889 
20890  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20891  old_value = *cur;
20892  *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
20893  *cur, max, is_modifyable, &style->progress, in);
20894  return (*cur != old_value);
20895 }
20896 
20897 NK_API nk_size nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
20898 {nk_progress(ctx, &cur, max, modifyable);return cur;}
20899 
20900 /*----------------------------------------------------------------
20901  *
20902  * EDIT
20903  *
20904  * --------------------------------------------------------------*/
20905 NK_API void
20906 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
20907 {
20908  nk_hash hash;
20909  struct nk_window *win;
20910 
20911  NK_ASSERT(ctx);
20912  NK_ASSERT(ctx->current);
20913  if (!ctx || !ctx->current) return;
20914 
20915  win = ctx->current;
20916  hash = win->edit.seq;
20917  win->edit.active = nk_true;
20918  win->edit.name = hash;
20919  if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
20921 }
20922 
20923 NK_API void
20924 nk_edit_unfocus(struct nk_context *ctx)
20925 {
20926  struct nk_window *win;
20927  NK_ASSERT(ctx);
20928  NK_ASSERT(ctx->current);
20929  if (!ctx || !ctx->current) return;
20930 
20931  win = ctx->current;
20932  win->edit.active = nk_false;
20933  win->edit.name = 0;
20934 }
20935 
20936 NK_API nk_flags
20937 nk_edit_string(struct nk_context *ctx, nk_flags flags,
20938  char *memory, int *len, int max, nk_plugin_filter filter)
20939 {
20940  nk_hash hash;
20941  nk_flags state;
20942  struct nk_text_edit *edit;
20943  struct nk_window *win;
20944 
20945  NK_ASSERT(ctx);
20946  NK_ASSERT(memory);
20947  NK_ASSERT(len);
20948  if (!ctx || !memory || !len)
20949  return 0;
20950 
20951  filter = (!filter) ? nk_filter_default: filter;
20952  win = ctx->current;
20953  hash = win->edit.seq;
20954  edit = &ctx->text_edit;
20955  nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
20957 
20958  if (win->edit.active && hash == win->edit.name) {
20959  if (flags & NK_EDIT_NO_CURSOR)
20960  edit->cursor = nk_utf_len(memory, *len);
20961  else edit->cursor = win->edit.cursor;
20962  if (!(flags & NK_EDIT_SELECTABLE)) {
20963  edit->select_start = win->edit.cursor;
20964  edit->select_end = win->edit.cursor;
20965  } else {
20966  edit->select_start = win->edit.sel_start;
20967  edit->select_end = win->edit.sel_end;
20968  }
20969  edit->mode = win->edit.mode;
20970  edit->scrollbar.x = (float)win->edit.scrollbar.x;
20971  edit->scrollbar.y = (float)win->edit.scrollbar.y;
20972  edit->active = nk_true;
20973  } else edit->active = nk_false;
20974 
20975  max = NK_MAX(1, max);
20976  *len = NK_MIN(*len, max-1);
20977  nk_str_init_fixed(&edit->string, memory, (nk_size)max);
20978  edit->string.buffer.allocated = (nk_size)*len;
20979  edit->string.len = nk_utf_len(memory, *len);
20980  state = nk_edit_buffer(ctx, flags, edit, filter);
20981  *len = (int)edit->string.buffer.allocated;
20982 
20983  if (edit->active) {
20984  win->edit.cursor = edit->cursor;
20985  win->edit.sel_start = edit->select_start;
20986  win->edit.sel_end = edit->select_end;
20987  win->edit.mode = edit->mode;
20988  win->edit.scrollbar.x = (nk_ushort)edit->scrollbar.x;
20989  win->edit.scrollbar.y = (nk_ushort)edit->scrollbar.y;
20990  }
20991  return state;
20992 }
20993 
20994 NK_API nk_flags
20995 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
20996  struct nk_text_edit *edit, nk_plugin_filter filter)
20997 {
20998  struct nk_window *win;
20999  struct nk_style *style;
21000  struct nk_input *in;
21001 
21002  enum nk_widget_layout_states state;
21003  struct nk_rect bounds;
21004 
21005  nk_flags ret_flags = 0;
21006  unsigned char prev_state;
21007  nk_hash hash;
21008 
21009  /* make sure correct values */
21010  NK_ASSERT(ctx);
21011  NK_ASSERT(edit);
21012  NK_ASSERT(ctx->current);
21013  NK_ASSERT(ctx->current->layout);
21014  if (!ctx || !ctx->current || !ctx->current->layout)
21015  return 0;
21016 
21017  win = ctx->current;
21018  style = &ctx->style;
21019  state = nk_widget(&bounds, ctx);
21020  if (!state) return state;
21021  in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21022 
21023  /* check if edit is currently hot item */
21024  hash = win->edit.seq++;
21025  if (win->edit.active && hash == win->edit.name) {
21026  if (flags & NK_EDIT_NO_CURSOR)
21027  edit->cursor = edit->string.len;
21028  if (!(flags & NK_EDIT_SELECTABLE)) {
21029  edit->select_start = edit->cursor;
21030  edit->select_end = edit->cursor;
21031  }
21032  if (flags & NK_EDIT_CLIPBOARD)
21033  edit->clip = ctx->clip;
21034  }
21035 
21036  filter = (!filter) ? nk_filter_default: filter;
21037  prev_state = (unsigned char)edit->active;
21038  in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
21039  ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
21040  filter, edit, &style->edit, in, style->font);
21041 
21042  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
21044  if (edit->active && prev_state != edit->active) {
21045  /* current edit is now hot */
21046  win->edit.active = nk_true;
21047  win->edit.name = hash;
21048  } else if (prev_state && !edit->active) {
21049  /* current edit is now cold */
21050  win->edit.active = nk_false;
21051  }
21052  return ret_flags;
21053 }
21054 
21055 NK_API nk_flags
21056 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
21057  char *buffer, int max, nk_plugin_filter filter)
21058 {
21059  nk_flags result;
21060  int len = nk_strlen(buffer);
21061  result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
21062  buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
21063  return result;
21064 }
21065 
21066 /*----------------------------------------------------------------
21067  *
21068  * PROPERTY
21069  *
21070  * --------------------------------------------------------------*/
21071 NK_INTERN struct nk_property_variant
21072 nk_property_variant_int(int value, int min_value, int max_value, int step)
21073 {
21074  struct nk_property_variant result;
21075  result.kind = NK_PROPERTY_INT;
21076  result.value.i = value;
21077  result.min_value.i = min_value;
21078  result.max_value.i = max_value;
21079  result.step.i = step;
21080  return result;
21081 }
21082 
21083 NK_INTERN struct nk_property_variant
21084 nk_property_variant_float(float value, float min_value, float max_value, float step)
21085 {
21086  struct nk_property_variant result;
21087  result.kind = NK_PROPERTY_FLOAT;
21088  result.value.f = value;
21089  result.min_value.f = min_value;
21090  result.max_value.f = max_value;
21091  result.step.f = step;
21092  return result;
21093 }
21094 
21095 NK_INTERN struct nk_property_variant
21096 nk_property_variant_double(double value, double min_value, double max_value,
21097  double step)
21098 {
21099  struct nk_property_variant result;
21100  result.kind = NK_PROPERTY_DOUBLE;
21101  result.value.d = value;
21102  result.min_value.d = min_value;
21103  result.max_value.d = max_value;
21104  result.step.d = step;
21105  return result;
21106 }
21107 
21108 NK_INTERN void
21109 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
21110  float inc_per_pixel, const enum nk_property_filter filter)
21111 {
21112  struct nk_window *win;
21113  struct nk_panel *layout;
21114  struct nk_input *in;
21115  const struct nk_style *style;
21116 
21117  struct nk_rect bounds;
21118  enum nk_widget_layout_states s;
21119 
21120  int *state = 0;
21121  nk_hash hash = 0;
21122  char *buffer = 0;
21123  int *len = 0;
21124  int *cursor = 0;
21125  int *select_begin = 0;
21126  int *select_end = 0;
21127  int old_state;
21128 
21129  char dummy_buffer[NK_MAX_NUMBER_BUFFER];
21130  int dummy_state = NK_PROPERTY_DEFAULT;
21131  int dummy_length = 0;
21132  int dummy_cursor = 0;
21133  int dummy_select_begin = 0;
21134  int dummy_select_end = 0;
21135 
21136  NK_ASSERT(ctx);
21137  NK_ASSERT(ctx->current);
21138  NK_ASSERT(ctx->current->layout);
21139  if (!ctx || !ctx->current || !ctx->current->layout)
21140  return;
21141 
21142  win = ctx->current;
21143  layout = win->layout;
21144  style = &ctx->style;
21145  s = nk_widget(&bounds, ctx);
21146  if (!s) return;
21147  in = (s == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21148 
21149  /* calculate hash from name */
21150  if (name[0] == '#') {
21151  hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
21152  name++; /* special number hash */
21153  } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
21154 
21155  /* check if property is currently hot item */
21156  if (win->property.active && hash == win->property.name) {
21157  buffer = win->property.buffer;
21158  len = &win->property.length;
21159  cursor = &win->property.cursor;
21160  state = &win->property.state;
21161  select_begin = &win->property.select_start;
21162  select_end = &win->property.select_end;
21163  } else {
21164  buffer = dummy_buffer;
21165  len = &dummy_length;
21166  cursor = &dummy_cursor;
21167  state = &dummy_state;
21168  select_begin = &dummy_select_begin;
21169  select_end = &dummy_select_end;
21170  }
21171 
21172  /* execute property widget */
21173  old_state = *state;
21174  ctx->text_edit.clip = ctx->clip;
21175  nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
21176  variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
21177  select_end, &style->property, filter, in, style->font, &ctx->text_edit,
21178  ctx->button_behavior);
21179 
21180  if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
21181  /* current property is now hot */
21182  win->property.active = 1;
21183  NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
21184  win->property.length = *len;
21185  win->property.cursor = *cursor;
21186  win->property.state = *state;
21187  win->property.name = hash;
21188  win->property.select_start = *select_begin;
21189  win->property.select_end = *select_end;
21190  if (*state == NK_PROPERTY_DRAG) {
21191  ctx->input.mouse.grab = nk_true;
21192  ctx->input.mouse.grabbed = nk_true;
21193  }
21194  }
21195 
21196  /* check if previously active property is now inactive */
21197  if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
21198  if (old_state == NK_PROPERTY_DRAG) {
21199  ctx->input.mouse.grab = nk_false;
21200  ctx->input.mouse.grabbed = nk_false;
21201  ctx->input.mouse.ungrab = nk_true;
21202  }
21203  win->property.active = 0;
21204  }
21205 }
21206 
21207 NK_API void
21208 nk_property_int(struct nk_context *ctx, const char *name,
21209  int min, int *val, int max, int step, float inc_per_pixel)
21210 {
21211  struct nk_property_variant variant;
21212  NK_ASSERT(ctx);
21213  NK_ASSERT(name);
21214  NK_ASSERT(val);
21215 
21216  if (!ctx || !ctx->current || !name || !val) return;
21217  variant = nk_property_variant_int(*val, min, max, step);
21218  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21219  *val = variant.value.i;
21220 }
21221 
21222 NK_API void
21223 nk_property_float(struct nk_context *ctx, const char *name,
21224  float min, float *val, float max, float step, float inc_per_pixel)
21225 {
21226  struct nk_property_variant variant;
21227  NK_ASSERT(ctx);
21228  NK_ASSERT(name);
21229  NK_ASSERT(val);
21230 
21231  if (!ctx || !ctx->current || !name || !val) return;
21232  variant = nk_property_variant_float(*val, min, max, step);
21233  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21234  *val = variant.value.f;
21235 }
21236 
21237 NK_API void
21238 nk_property_double(struct nk_context *ctx, const char *name,
21239  double min, double *val, double max, double step, float inc_per_pixel)
21240 {
21241  struct nk_property_variant variant;
21242  NK_ASSERT(ctx);
21243  NK_ASSERT(name);
21244  NK_ASSERT(val);
21245 
21246  if (!ctx || !ctx->current || !name || !val) return;
21247  variant = nk_property_variant_double(*val, min, max, step);
21248  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21249  *val = variant.value.d;
21250 }
21251 
21252 NK_API int
21253 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
21254  int max, int step, float inc_per_pixel)
21255 {
21256  struct nk_property_variant variant;
21257  NK_ASSERT(ctx);
21258  NK_ASSERT(name);
21259 
21260  if (!ctx || !ctx->current || !name) return val;
21261  variant = nk_property_variant_int(val, min, max, step);
21262  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21263  val = variant.value.i;
21264  return val;
21265 }
21266 
21267 NK_API float
21268 nk_propertyf(struct nk_context *ctx, const char *name, float min,
21269  float val, float max, float step, float inc_per_pixel)
21270 {
21271  struct nk_property_variant variant;
21272  NK_ASSERT(ctx);
21273  NK_ASSERT(name);
21274 
21275  if (!ctx || !ctx->current || !name) return val;
21276  variant = nk_property_variant_float(val, min, max, step);
21277  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21278  val = variant.value.f;
21279  return val;
21280 }
21281 
21282 NK_API double
21283 nk_propertyd(struct nk_context *ctx, const char *name, double min,
21284  double val, double max, double step, float inc_per_pixel)
21285 {
21286  struct nk_property_variant variant;
21287  NK_ASSERT(ctx);
21288  NK_ASSERT(name);
21289 
21290  if (!ctx || !ctx->current || !name) return val;
21291  variant = nk_property_variant_double(val, min, max, step);
21292  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21293  val = variant.value.d;
21294  return val;
21295 }
21296 
21297 /*----------------------------------------------------------------
21298  *
21299  * COLOR PICKER
21300  *
21301  * --------------------------------------------------------------*/
21302 NK_API int
21303 nk_color_pick(struct nk_context * ctx, struct nk_color *color,
21304  enum nk_color_format fmt)
21305 {
21306  struct nk_window *win;
21307  struct nk_panel *layout;
21308  const struct nk_style *config;
21309  const struct nk_input *in;
21310 
21311  enum nk_widget_layout_states state;
21312  struct nk_rect bounds;
21313 
21314  NK_ASSERT(ctx);
21315  NK_ASSERT(color);
21316  NK_ASSERT(ctx->current);
21317  NK_ASSERT(ctx->current->layout);
21318  if (!ctx || !ctx->current || !ctx->current->layout || !color)
21319  return 0;
21320 
21321  win = ctx->current;
21322  config = &ctx->style;
21323  layout = win->layout;
21324  state = nk_widget(&bounds, ctx);
21325  if (!state) return 0;
21326  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21327  return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
21328  nk_vec2(0,0), in, config->font);
21329 }
21330 
21331 NK_API struct nk_color
21332 nk_color_picker(struct nk_context *ctx, struct nk_color color,
21333  enum nk_color_format fmt)
21334 {
21335  nk_color_pick(ctx, &color, fmt);
21336  return color;
21337 }
21338 
21339 /* -------------------------------------------------------------
21340  *
21341  * CHART
21342  *
21343  * --------------------------------------------------------------*/
21344 NK_API int
21345 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
21346  struct nk_color color, struct nk_color highlight,
21347  int count, float min_value, float max_value)
21348 {
21349  struct nk_window *win;
21350  struct nk_chart *chart;
21351  const struct nk_style *config;
21352  const struct nk_style_chart *style;
21353 
21354  const struct nk_style_item *background;
21355  struct nk_rect bounds = {0, 0, 0, 0};
21356 
21357  NK_ASSERT(ctx);
21358  NK_ASSERT(ctx->current);
21359  NK_ASSERT(ctx->current->layout);
21360 
21361  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
21362  if (!nk_widget(&bounds, ctx)) {
21363  chart = &ctx->current->layout->chart;
21364  nk_zero(chart, sizeof(*chart));
21365  return 0;
21366  }
21367 
21368  win = ctx->current;
21369  config = &ctx->style;
21370  chart = &win->layout->chart;
21371  style = &config->chart;
21372 
21373  /* setup basic generic chart */
21374  nk_zero(chart, sizeof(*chart));
21375  chart->x = bounds.x + style->padding.x;
21376  chart->y = bounds.y + style->padding.y;
21377  chart->w = bounds.w - 2 * style->padding.x;
21378  chart->h = bounds.h - 2 * style->padding.y;
21379  chart->w = NK_MAX(chart->w, 2 * style->padding.x);
21380  chart->h = NK_MAX(chart->h, 2 * style->padding.y);
21381 
21382  /* add first slot into chart */
21383  {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21384  slot->type = type;
21385  slot->count = count;
21386  slot->color = color;
21387  slot->highlight = highlight;
21388  slot->min = NK_MIN(min_value, max_value);
21389  slot->max = NK_MAX(min_value, max_value);
21390  slot->range = slot->max - slot->min;}
21391 
21392  /* draw chart background */
21393  background = &style->background;
21394  if (background->type == NK_STYLE_ITEM_IMAGE) {
21395  nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
21396  } else {
21397  nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
21398  nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
21399  style->rounding, style->background.data.color);
21400  }
21401  return 1;
21402 }
21403 
21404 NK_API int
21405 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
21406  int count, float min_value, float max_value)
21407 {return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21408 
21409 NK_API void
21410 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
21411  struct nk_color color, struct nk_color highlight,
21412  int count, float min_value, float max_value)
21413 {
21414  NK_ASSERT(ctx);
21415  NK_ASSERT(ctx->current);
21416  NK_ASSERT(ctx->current->layout);
21417  NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
21418  if (!ctx || !ctx->current || !ctx->current->layout) return;
21419  if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
21420 
21421  /* add another slot into the graph */
21422  {struct nk_chart *chart = &ctx->current->layout->chart;
21423  struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21424  slot->type = type;
21425  slot->count = count;
21426  slot->color = color;
21427  slot->highlight = highlight;
21428  slot->min = NK_MIN(min_value, max_value);
21429  slot->max = NK_MAX(min_value, max_value);
21430  slot->range = slot->max - slot->min;}
21431 }
21432 
21433 NK_API void
21434 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
21435  int count, float min_value, float max_value)
21436 {nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21437 
21438 NK_INTERN nk_flags
21439 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
21440  struct nk_chart *g, float value, int slot)
21441 {
21442  struct nk_panel *layout = win->layout;
21443  const struct nk_input *i = &ctx->input;
21444  struct nk_command_buffer *out = &win->buffer;
21445 
21446  nk_flags ret = 0;
21447  struct nk_vec2 cur;
21448  struct nk_rect bounds;
21449  struct nk_color color;
21450  float step;
21451  float range;
21452  float ratio;
21453 
21454  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21455  step = g->w / (float)g->slots[slot].count;
21456  range = g->slots[slot].max - g->slots[slot].min;
21457  ratio = (value - g->slots[slot].min) / range;
21458 
21459  if (g->slots[slot].index == 0) {
21460  /* first data point does not have a connection */
21461  g->slots[slot].last.x = g->x;
21462  g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
21463 
21464  bounds.x = g->slots[slot].last.x - 2;
21465  bounds.y = g->slots[slot].last.y - 2;
21466  bounds.w = bounds.h = 4;
21467 
21468  color = g->slots[slot].color;
21469  if (!(layout->flags & NK_WINDOW_ROM) &&
21470  NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
21471  ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
21472  ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
21474  color = g->slots[slot].highlight;
21475  }
21476  nk_fill_rect(out, bounds, 0, color);
21477  g->slots[slot].index += 1;
21478  return ret;
21479  }
21480 
21481  /* draw a line between the last data point and the new one */
21482  color = g->slots[slot].color;
21483  cur.x = g->x + (float)(step * (float)g->slots[slot].index);
21484  cur.y = (g->y + g->h) - (ratio * (float)g->h);
21485  nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
21486 
21487  bounds.x = cur.x - 3;
21488  bounds.y = cur.y - 3;
21489  bounds.w = bounds.h = 6;
21490 
21491  /* user selection of current data point */
21492  if (!(layout->flags & NK_WINDOW_ROM)) {
21493  if (nk_input_is_mouse_hovering_rect(i, bounds)) {
21494  ret = NK_CHART_HOVERING;
21495  ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
21497  color = g->slots[slot].highlight;
21498  }
21499  }
21500  nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
21501 
21502  /* save current data point position */
21503  g->slots[slot].last.x = cur.x;
21504  g->slots[slot].last.y = cur.y;
21505  g->slots[slot].index += 1;
21506  return ret;
21507 }
21508 
21509 NK_INTERN nk_flags
21510 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
21511  struct nk_chart *chart, float value, int slot)
21512 {
21513  struct nk_command_buffer *out = &win->buffer;
21514  const struct nk_input *in = &ctx->input;
21515  struct nk_panel *layout = win->layout;
21516 
21517  float ratio;
21518  nk_flags ret = 0;
21519  struct nk_color color;
21520  struct nk_rect item = {0,0,0,0};
21521 
21522  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21523  if (chart->slots[slot].index >= chart->slots[slot].count)
21524  return nk_false;
21525  if (chart->slots[slot].count) {
21526  float padding = (float)(chart->slots[slot].count-1);
21527  item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
21528  }
21529 
21530  /* calculate bounds of current bar chart entry */
21531  color = chart->slots[slot].color;;
21532  item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
21533  if (value >= 0) {
21534  ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
21535  item.y = (chart->y + chart->h) - chart->h * ratio;
21536  } else {
21537  ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
21538  item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
21539  }
21540  item.x = chart->x + ((float)chart->slots[slot].index * item.w);
21541  item.x = item.x + ((float)chart->slots[slot].index);
21542 
21543  /* user chart bar selection */
21544  if (!(layout->flags & NK_WINDOW_ROM) &&
21545  NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
21546  ret = NK_CHART_HOVERING;
21547  ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
21549  color = chart->slots[slot].highlight;
21550  }
21551  nk_fill_rect(out, item, 0, color);
21552  chart->slots[slot].index += 1;
21553  return ret;
21554 }
21555 
21556 NK_API nk_flags
21557 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
21558 {
21559  nk_flags flags;
21560  struct nk_window *win;
21561 
21562  NK_ASSERT(ctx);
21563  NK_ASSERT(ctx->current);
21564  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21565  NK_ASSERT(slot < ctx->current->layout->chart.slot);
21566  if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
21567  if (slot >= ctx->current->layout->chart.slot) return nk_false;
21568 
21569  win = ctx->current;
21570  if (win->layout->chart.slot < slot) return nk_false;
21571  switch (win->layout->chart.slots[slot].type) {
21572  case NK_CHART_LINES:
21573  flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
21574  case NK_CHART_COLUMN:
21575  flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
21576  default:
21577  case NK_CHART_MAX:
21578  flags = 0;
21579  }
21580  return flags;
21581 }
21582 
21583 NK_API nk_flags
21584 nk_chart_push(struct nk_context *ctx, float value)
21585 {return nk_chart_push_slot(ctx, value, 0);}
21586 
21587 NK_API void
21588 nk_chart_end(struct nk_context *ctx)
21589 {
21590  struct nk_window *win;
21591  struct nk_chart *chart;
21592 
21593  NK_ASSERT(ctx);
21594  NK_ASSERT(ctx->current);
21595  if (!ctx || !ctx->current)
21596  return;
21597 
21598  win = ctx->current;
21599  chart = &win->layout->chart;
21600  NK_MEMSET(chart, 0, sizeof(*chart));
21601  return;
21602 }
21603 
21604 NK_API void
21605 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
21606  int count, int offset)
21607 {
21608  int i = 0;
21609  float min_value;
21610  float max_value;
21611 
21612  NK_ASSERT(ctx);
21613  NK_ASSERT(values);
21614  if (!ctx || !values || !count) return;
21615 
21616  min_value = values[offset];
21617  max_value = values[offset];
21618  for (i = 0; i < count; ++i) {
21619  min_value = NK_MIN(values[i + offset], min_value);
21620  max_value = NK_MAX(values[i + offset], max_value);
21621  }
21622  nk_chart_begin(ctx, type, count, min_value, max_value);
21623  for (i = 0; i < count; ++i)
21624  nk_chart_push(ctx, values[i + offset]);
21625  nk_chart_end(ctx);
21626 }
21627 
21628 NK_API void
21629 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
21630  float(*value_getter)(void* user, int index), int count, int offset)
21631 {
21632  int i = 0;
21633  float min_value;
21634  float max_value;
21635 
21636  NK_ASSERT(ctx);
21637  NK_ASSERT(value_getter);
21638  if (!ctx || !value_getter || !count) return;
21639 
21640  max_value = min_value = value_getter(userdata, offset);
21641  for (i = 0; i < count; ++i) {
21642  float value = value_getter(userdata, i + offset);
21643  min_value = NK_MIN(value, min_value);
21644  max_value = NK_MAX(value, max_value);
21645  }
21646  nk_chart_begin(ctx, type, count, min_value, max_value);
21647  for (i = 0; i < count; ++i)
21648  nk_chart_push(ctx, value_getter(userdata, i + offset));
21649  nk_chart_end(ctx);
21650 }
21651 
21652 /* -------------------------------------------------------------
21653  *
21654  * GROUP
21655  *
21656  * --------------------------------------------------------------*/
21657 NK_API int
21659  nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
21660 {
21661  struct nk_rect bounds;
21662  struct nk_window panel;
21663  struct nk_window *win;
21664 
21665  win = ctx->current;
21666  nk_panel_alloc_space(&bounds, ctx);
21667  {const struct nk_rect *c = &win->layout->clip;
21668  if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
21669  !(flags & NK_WINDOW_MOVABLE)) {
21670  return 0;
21671  }}
21672  if (win->flags & NK_WINDOW_ROM)
21673  flags |= NK_WINDOW_ROM;
21674 
21675  /* initialize a fake window to create the panel from */
21676  nk_zero(&panel, sizeof(panel));
21677  panel.bounds = bounds;
21678  panel.flags = flags;
21679  panel.scrollbar.x = *x_offset;
21680  panel.scrollbar.y = *y_offset;
21681  panel.buffer = win->buffer;
21682  panel.layout = (struct nk_panel*)nk_create_panel(ctx);
21683  ctx->current = &panel;
21684  nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
21685 
21686  win->buffer = panel.buffer;
21687  win->buffer.clip = panel.layout->clip;
21688  panel.layout->offset_x = x_offset;
21689  panel.layout->offset_y = y_offset;
21690  panel.layout->parent = win->layout;
21691  win->layout = panel.layout;
21692 
21693  ctx->current = win;
21694  if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
21695  (panel.layout->flags & NK_WINDOW_MINIMIZED))
21696  {
21697  nk_flags f = panel.layout->flags;
21698  nk_group_scrolled_end(ctx);
21699  if (f & NK_WINDOW_CLOSED)
21700  return NK_WINDOW_CLOSED;
21701  if (f & NK_WINDOW_MINIMIZED)
21702  return NK_WINDOW_MINIMIZED;
21703  }
21704  return 1;
21705 }
21706 
21707 NK_API void
21708 nk_group_scrolled_end(struct nk_context *ctx)
21709 {
21710  struct nk_window *win;
21711  struct nk_panel *parent;
21712  struct nk_panel *g;
21713 
21714  struct nk_rect clip;
21715  struct nk_window pan;
21716  struct nk_vec2 panel_padding;
21717 
21718  NK_ASSERT(ctx);
21719  NK_ASSERT(ctx->current);
21720  if (!ctx || !ctx->current)
21721  return;
21722 
21723  /* make sure nk_group_begin was called correctly */
21724  NK_ASSERT(ctx->current);
21725  win = ctx->current;
21726  NK_ASSERT(win->layout);
21727  g = win->layout;
21728  NK_ASSERT(g->parent);
21729  parent = g->parent;
21730 
21731  /* dummy window */
21732  nk_zero_struct(pan);
21733  panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
21734  pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
21735  pan.bounds.x = g->bounds.x - panel_padding.x;
21736  pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
21737  pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
21738  if (g->flags & NK_WINDOW_BORDER) {
21739  pan.bounds.x -= g->border;
21740  pan.bounds.y -= g->border;
21741  pan.bounds.w += 2*g->border;
21742  pan.bounds.h += 2*g->border;
21743  }
21744  if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
21745  pan.bounds.w += ctx->style.window.scrollbar_size.x;
21746  pan.bounds.h += ctx->style.window.scrollbar_size.y;
21747  }
21748  pan.scrollbar.x = *g->offset_x;
21749  pan.scrollbar.y = *g->offset_y;
21750  pan.flags = g->flags;
21751  pan.buffer = win->buffer;
21752  pan.layout = g;
21753  pan.parent = win;
21754  ctx->current = &pan;
21755 
21756  /* make sure group has correct clipping rectangle */
21757  nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
21758  pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
21759  nk_push_scissor(&pan.buffer, clip);
21760  nk_end(ctx);
21761 
21762  win->buffer = pan.buffer;
21763  nk_push_scissor(&win->buffer, parent->clip);
21764  ctx->current = win;
21765  win->layout = parent;
21766  g->bounds = pan.bounds;
21767  return;
21768 }
21769 
21770 NK_API int
21772  struct nk_scroll *scroll, const char *title, nk_flags flags)
21773 {return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);}
21774 
21775 NK_API int
21776 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
21777 {
21778  int title_len;
21779  nk_hash title_hash;
21780  struct nk_window *win;
21781  nk_uint *x_offset;
21782  nk_uint *y_offset;
21783 
21784  NK_ASSERT(ctx);
21785  NK_ASSERT(title);
21786  NK_ASSERT(ctx->current);
21787  NK_ASSERT(ctx->current->layout);
21788  if (!ctx || !ctx->current || !ctx->current->layout || !title)
21789  return 0;
21790 
21791  /* find persistent group scrollbar value */
21792  win = ctx->current;
21793  title_len = (int)nk_strlen(title);
21794  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
21795  x_offset = nk_find_value(win, title_hash);
21796  if (!x_offset) {
21797  x_offset = nk_add_value(ctx, win, title_hash, 0);
21798  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
21799 
21800  NK_ASSERT(x_offset);
21801  NK_ASSERT(y_offset);
21802  if (!x_offset || !y_offset) return 0;
21803  *x_offset = *y_offset = 0;
21804  } else y_offset = nk_find_value(win, title_hash+1);
21805  return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
21806 }
21807 
21808 NK_API void
21809 nk_group_end(struct nk_context *ctx)
21810 {nk_group_scrolled_end(ctx);}
21811 
21812 NK_API int
21813 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
21814  const char *title, nk_flags flags, int row_height, int row_count)
21815 {
21816  int title_len;
21817  nk_hash title_hash;
21818  nk_uint *x_offset;
21819  nk_uint *y_offset;
21820 
21821  int result;
21822  struct nk_window *win;
21823  struct nk_panel *layout;
21824  const struct nk_style *style;
21825  struct nk_vec2 item_spacing;
21826 
21827  NK_ASSERT(ctx);
21828  NK_ASSERT(view);
21829  NK_ASSERT(title);
21830  if (!ctx || !view || !title) return 0;
21831 
21832  win = ctx->current;
21833  style = &ctx->style;
21834  item_spacing = style->window.spacing;
21835  row_height += NK_MAX(0, (int)item_spacing.y);
21836 
21837  /* find persistent list view scrollbar offset */
21838  title_len = (int)nk_strlen(title);
21839  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
21840  x_offset = nk_find_value(win, title_hash);
21841  if (!x_offset) {
21842  x_offset = nk_add_value(ctx, win, title_hash, 0);
21843  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
21844 
21845  NK_ASSERT(x_offset);
21846  NK_ASSERT(y_offset);
21847  if (!x_offset || !y_offset) return 0;
21848  *x_offset = *y_offset = 0;
21849  } else y_offset = nk_find_value(win, title_hash+1);
21850  view->scroll_value = *y_offset;
21851  view->scroll_pointer = y_offset;
21852 
21853  *y_offset = 0;
21854  result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
21855  win = ctx->current;
21856  layout = win->layout;
21857 
21858  view->total_height = row_height * NK_MAX(row_count,1);
21859  view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
21860  view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0);
21861  view->end = view->begin + view->count;
21862  view->ctx = ctx;
21863  return result;
21864 }
21865 
21866 NK_API void
21867 nk_list_view_end(struct nk_list_view *view)
21868 {
21869  struct nk_context *ctx;
21870  struct nk_window *win;
21871  struct nk_panel *layout;
21872 
21873  NK_ASSERT(view);
21874  NK_ASSERT(view->ctx);
21875  NK_ASSERT(view->scroll_pointer);
21876  if (!view || !view->ctx) return;
21877 
21878  ctx = view->ctx;
21879  win = ctx->current;
21880  layout = win->layout;
21881  layout->at_y = layout->bounds.y + (float)view->total_height;
21882  *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
21883  nk_group_end(view->ctx);
21884 }
21885 
21886 /* --------------------------------------------------------------
21887  *
21888  * POPUP
21889  *
21890  * --------------------------------------------------------------*/
21891 NK_API int
21892 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
21893  const char *title, nk_flags flags, struct nk_rect rect)
21894 {
21895  struct nk_window *popup;
21896  struct nk_window *win;
21897  struct nk_panel *panel;
21898 
21899  int title_len;
21900  nk_hash title_hash;
21901  nk_size allocated;
21902 
21903  NK_ASSERT(ctx);
21904  NK_ASSERT(title);
21905  NK_ASSERT(ctx->current);
21906  NK_ASSERT(ctx->current->layout);
21907  if (!ctx || !ctx->current || !ctx->current->layout)
21908  return 0;
21909 
21910  win = ctx->current;
21911  panel = win->layout;
21912  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
21913  (void)panel;
21914  title_len = (int)nk_strlen(title);
21915  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
21916 
21917  popup = win->popup.win;
21918  if (!popup) {
21919  popup = (struct nk_window*)nk_create_window(ctx);
21920  popup->parent = win;
21921  win->popup.win = popup;
21922  win->popup.active = 0;
21923  win->popup.type = NK_PANEL_POPUP;
21924  }
21925 
21926  /* make sure we have to correct popup */
21927  if (win->popup.name != title_hash) {
21928  if (!win->popup.active) {
21929  nk_zero(popup, sizeof(*popup));
21930  win->popup.name = title_hash;
21931  win->popup.active = 1;
21932  win->popup.type = NK_PANEL_POPUP;
21933  } else return 0;
21934  }
21935 
21936  /* popup position is local to window */
21937  ctx->current = popup;
21938  rect.x += win->layout->clip.x;
21939  rect.y += win->layout->clip.y;
21940 
21941  /* setup popup data */
21942  popup->parent = win;
21943  popup->bounds = rect;
21944  popup->seq = ctx->seq;
21945  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
21946  popup->flags = flags;
21947  popup->flags |= NK_WINDOW_BORDER;
21948  if (type == NK_POPUP_DYNAMIC)
21949  popup->flags |= NK_WINDOW_DYNAMIC;
21950 
21951  popup->buffer = win->buffer;
21952  nk_start_popup(ctx, win);
21953  allocated = ctx->memory.allocated;
21954  nk_push_scissor(&popup->buffer, nk_null_rect);
21955 
21956  if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
21957  /* popup is running therefore invalidate parent panels */
21958  struct nk_panel *root;
21959  root = win->layout;
21960  while (root) {
21961  root->flags |= NK_WINDOW_ROM;
21962  root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
21963  root = root->parent;
21964  }
21965  win->popup.active = 1;
21966  popup->layout->offset_x = &popup->scrollbar.x;
21967  popup->layout->offset_y = &popup->scrollbar.y;
21968  popup->layout->parent = win->layout;
21969  return 1;
21970  } else {
21971  /* popup was closed/is invalid so cleanup */
21972  struct nk_panel *root;
21973  root = win->layout;
21974  while (root) {
21975  root->flags |= NK_WINDOW_REMOVE_ROM;
21976  root = root->parent;
21977  }
21978  win->popup.buf.active = 0;
21979  win->popup.active = 0;
21980  ctx->memory.allocated = allocated;
21981  ctx->current = win;
21982  nk_free_panel(ctx, popup->layout);
21983  popup->layout = 0;
21984  return 0;
21985  }
21986 }
21987 
21988 NK_INTERN int
21989 nk_nonblock_begin(struct nk_context *ctx,
21990  nk_flags flags, struct nk_rect body, struct nk_rect header,
21991  enum nk_panel_type panel_type)
21992 {
21993  struct nk_window *popup;
21994  struct nk_window *win;
21995  struct nk_panel *panel;
21996  int is_active = nk_true;
21997 
21998  NK_ASSERT(ctx);
21999  NK_ASSERT(ctx->current);
22000  NK_ASSERT(ctx->current->layout);
22001  if (!ctx || !ctx->current || !ctx->current->layout)
22002  return 0;
22003 
22004  /* popups cannot have popups */
22005  win = ctx->current;
22006  panel = win->layout;
22007  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
22008  (void)panel;
22009  popup = win->popup.win;
22010  if (!popup) {
22011  /* create window for nonblocking popup */
22012  popup = (struct nk_window*)nk_create_window(ctx);
22013  popup->parent = win;
22014  win->popup.win = popup;
22015  win->popup.type = panel_type;
22016  nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
22017  } else {
22018  /* close the popup if user pressed outside or in the header */
22019  int pressed, in_body, in_header;
22021  in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22022  in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
22023  if (pressed && (!in_body || in_header))
22024  is_active = nk_false;
22025  }
22026  win->popup.header = header;
22027 
22028  if (!is_active) {
22029  /* remove read only mode from all parent panels */
22030  struct nk_panel *root = win->layout;
22031  while (root) {
22032  root->flags |= NK_WINDOW_REMOVE_ROM;
22033  root = root->parent;
22034  }
22035  return is_active;
22036  }
22037 
22038  popup->bounds = body;
22039  popup->parent = win;
22040  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
22041  popup->flags = flags;
22042  popup->flags |= NK_WINDOW_BORDER;
22043  popup->flags |= NK_WINDOW_DYNAMIC;
22044  popup->seq = ctx->seq;
22045  win->popup.active = 1;
22046  NK_ASSERT(popup->layout);
22047 
22048  nk_start_popup(ctx, win);
22049  popup->buffer = win->buffer;
22050  nk_push_scissor(&popup->buffer, nk_null_rect);
22051  ctx->current = popup;
22052 
22053  nk_panel_begin(ctx, 0, panel_type);
22054  win->buffer = popup->buffer;
22055  popup->layout->parent = win->layout;
22056  popup->layout->offset_x = &popup->scrollbar.x;
22057  popup->layout->offset_y = &popup->scrollbar.y;
22058 
22059  /* set read only mode to all parent panels */
22060  {struct nk_panel *root;
22061  root = win->layout;
22062  while (root) {
22063  root->flags |= NK_WINDOW_ROM;
22064  root = root->parent;
22065  }}
22066  return is_active;
22067 }
22068 
22069 NK_API void
22070 nk_popup_close(struct nk_context *ctx)
22071 {
22072  struct nk_window *popup;
22073  NK_ASSERT(ctx);
22074  if (!ctx || !ctx->current) return;
22075 
22076  popup = ctx->current;
22077  NK_ASSERT(popup->parent);
22078  NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
22079  popup->flags |= NK_WINDOW_HIDDEN;
22080 }
22081 
22082 NK_API void
22083 nk_popup_end(struct nk_context *ctx)
22084 {
22085  struct nk_window *win;
22086  struct nk_window *popup;
22087 
22088  NK_ASSERT(ctx);
22089  NK_ASSERT(ctx->current);
22090  NK_ASSERT(ctx->current->layout);
22091  if (!ctx || !ctx->current || !ctx->current->layout)
22092  return;
22093 
22094  popup = ctx->current;
22095  if (!popup->parent) return;
22096  win = popup->parent;
22097  if (popup->flags & NK_WINDOW_HIDDEN) {
22098  struct nk_panel *root;
22099  root = win->layout;
22100  while (root) {
22101  root->flags |= NK_WINDOW_REMOVE_ROM;
22102  root = root->parent;
22103  }
22104  win->popup.active = 0;
22105  }
22106  nk_push_scissor(&popup->buffer, nk_null_rect);
22107  nk_end(ctx);
22108 
22109  win->buffer = popup->buffer;
22110  nk_finish_popup(ctx, win);
22111  ctx->current = win;
22112  nk_push_scissor(&win->buffer, win->layout->clip);
22113 }
22114 /* -------------------------------------------------------------
22115  *
22116  * TOOLTIP
22117  *
22118  * -------------------------------------------------------------- */
22119 NK_API int
22120 nk_tooltip_begin(struct nk_context *ctx, float width)
22121 {
22122  struct nk_window *win;
22123  const struct nk_input *in;
22124  struct nk_rect bounds;
22125  int ret;
22126 
22127  NK_ASSERT(ctx);
22128  NK_ASSERT(ctx->current);
22129  NK_ASSERT(ctx->current->layout);
22130  if (!ctx || !ctx->current || !ctx->current->layout)
22131  return 0;
22132 
22133  /* make sure that no nonblocking popup is currently active */
22134  win = ctx->current;
22135  in = &ctx->input;
22136  if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
22137  return 0;
22138 
22139  bounds.w = width;
22140  bounds.h = nk_null_rect.h;
22141  bounds.x = (in->mouse.pos.x + 1) - win->layout->clip.x;
22142  bounds.y = (in->mouse.pos.y + 1) - win->layout->clip.y;
22143 
22144  ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
22145  "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
22146  if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
22147  win->popup.type = NK_PANEL_TOOLTIP;
22149  return ret;
22150 }
22151 
22152 NK_API void
22153 nk_tooltip_end(struct nk_context *ctx)
22154 {
22155  NK_ASSERT(ctx);
22156  NK_ASSERT(ctx->current);
22157  if (!ctx || !ctx->current) return;
22158  ctx->current->seq--;
22159  nk_popup_close(ctx);
22160  nk_popup_end(ctx);
22161 }
22162 
22163 NK_API void
22164 nk_tooltip(struct nk_context *ctx, const char *text)
22165 {
22166  const struct nk_style *style;
22167  struct nk_vec2 padding;
22168 
22169  int text_len;
22170  float text_width;
22171  float text_height;
22172 
22173  NK_ASSERT(ctx);
22174  NK_ASSERT(ctx->current);
22175  NK_ASSERT(ctx->current->layout);
22176  NK_ASSERT(text);
22177  if (!ctx || !ctx->current || !ctx->current->layout || !text)
22178  return;
22179 
22180  /* fetch configuration data */
22181  style = &ctx->style;
22182  padding = style->window.padding;
22183 
22184  /* calculate size of the text and tooltip */
22185  text_len = nk_strlen(text);
22186  text_width = style->font->width(style->font->userdata,
22187  style->font->height, text, text_len);
22188  text_width += (4 * padding.x);
22189  text_height = (style->font->height + 2 * padding.y);
22190 
22191  /* execute tooltip and fill with text */
22192  if (nk_tooltip_begin(ctx, (float)text_width)) {
22193  nk_layout_row_dynamic(ctx, (float)text_height, 1);
22194  nk_text(ctx, text, text_len, NK_TEXT_LEFT);
22195  nk_tooltip_end(ctx);
22196  }
22197 }
22198 /* -------------------------------------------------------------
22199  *
22200  * CONTEXTUAL
22201  *
22202  * -------------------------------------------------------------- */
22203 NK_API int
22204 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
22205  struct nk_rect trigger_bounds)
22206 {
22207  struct nk_window *win;
22208  struct nk_window *popup;
22209  struct nk_rect body;
22210 
22211  NK_STORAGE const struct nk_rect null_rect = {0,0,0,0};
22212  int is_clicked = 0;
22213  int is_active = 0;
22214  int is_open = 0;
22215  int ret = 0;
22216 
22217  NK_ASSERT(ctx);
22218  NK_ASSERT(ctx->current);
22219  NK_ASSERT(ctx->current->layout);
22220  if (!ctx || !ctx->current || !ctx->current->layout)
22221  return 0;
22222 
22223  win = ctx->current;
22224  ++win->popup.con_count;
22225 
22226  /* check if currently active contextual is active */
22227  popup = win->popup.win;
22228  is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
22229  is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
22230  if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
22231  return 0;
22232  if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked))
22233  return 0;
22234 
22235  /* calculate contextual position on click */
22236  win->popup.active_con = win->popup.con_count;
22237  if (is_clicked) {
22238  body.x = ctx->input.mouse.pos.x;
22239  body.y = ctx->input.mouse.pos.y;
22240  } else {
22241  body.x = popup->bounds.x;
22242  body.y = popup->bounds.y;
22243  }
22244  body.w = size.x;
22245  body.h = size.y;
22246 
22247  /* start nonblocking contextual popup */
22248  ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
22249  null_rect, NK_PANEL_CONTEXTUAL);
22250  if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
22251  else {
22252  win->popup.active_con = 0;
22253  if (win->popup.win)
22254  win->popup.win->flags = 0;
22255  }
22256  return ret;
22257 }
22258 
22259 NK_API int
22260 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
22261  nk_flags alignment)
22262 {
22263  struct nk_window *win;
22264  const struct nk_input *in;
22265  const struct nk_style *style;
22266 
22267  struct nk_rect bounds;
22268  enum nk_widget_layout_states state;
22269 
22270  NK_ASSERT(ctx);
22271  NK_ASSERT(ctx->current);
22272  NK_ASSERT(ctx->current->layout);
22273  if (!ctx || !ctx->current || !ctx->current->layout)
22274  return 0;
22275 
22276  win = ctx->current;
22277  style = &ctx->style;
22278  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22279  if (!state) return nk_false;
22280 
22281  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22282  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
22283  text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
22284  nk_contextual_close(ctx);
22285  return nk_true;
22286  }
22287  return nk_false;
22288 }
22289 
22290 NK_API int nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
22291 {return nk_contextual_item_text(ctx, label, nk_strlen(label), align);}
22292 
22293 NK_API int
22294 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
22295  const char *text, int len, nk_flags align)
22296 {
22297  struct nk_window *win;
22298  const struct nk_input *in;
22299  const struct nk_style *style;
22300 
22301  struct nk_rect bounds;
22302  enum nk_widget_layout_states state;
22303 
22304  NK_ASSERT(ctx);
22305  NK_ASSERT(ctx->current);
22306  NK_ASSERT(ctx->current->layout);
22307  if (!ctx || !ctx->current || !ctx->current->layout)
22308  return 0;
22309 
22310  win = ctx->current;
22311  style = &ctx->style;
22312  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22313  if (!state) return nk_false;
22314 
22315  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22316  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
22317  img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
22318  nk_contextual_close(ctx);
22319  return nk_true;
22320  }
22321  return nk_false;
22322 }
22323 
22324 NK_API int nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
22325  const char *label, nk_flags align)
22326 {return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);}
22327 
22328 NK_API int
22330  const char *text, int len, nk_flags align)
22331 {
22332  struct nk_window *win;
22333  const struct nk_input *in;
22334  const struct nk_style *style;
22335 
22336  struct nk_rect bounds;
22337  enum nk_widget_layout_states state;
22338 
22339  NK_ASSERT(ctx);
22340  NK_ASSERT(ctx->current);
22341  NK_ASSERT(ctx->current->layout);
22342  if (!ctx || !ctx->current || !ctx->current->layout)
22343  return 0;
22344 
22345  win = ctx->current;
22346  style = &ctx->style;
22347  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22348  if (!state) return nk_false;
22349 
22350  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22351  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
22352  symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
22353  nk_contextual_close(ctx);
22354  return nk_true;
22355  }
22356  return nk_false;
22357 }
22358 
22360  const char *text, nk_flags align)
22361 {return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);}
22362 
22363 NK_API void
22364 nk_contextual_close(struct nk_context *ctx)
22365 {
22366  NK_ASSERT(ctx);
22367  NK_ASSERT(ctx->current);
22368  NK_ASSERT(ctx->current->layout);
22369  if (!ctx || !ctx->current || !ctx->current->layout) return;
22370  nk_popup_close(ctx);
22371 }
22372 
22373 NK_API void
22374 nk_contextual_end(struct nk_context *ctx)
22375 {
22376  struct nk_window *popup;
22377  struct nk_panel *panel;
22378  NK_ASSERT(ctx);
22379  NK_ASSERT(ctx->current);
22380  if (!ctx || !ctx->current) return;
22381 
22382  popup = ctx->current;
22383  panel = popup->layout;
22384  NK_ASSERT(popup->parent);
22385  NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
22386  if (panel->flags & NK_WINDOW_DYNAMIC) {
22387  /* Close behavior
22388  This is a bit hack solution since we do not now before we end our popup
22389  how big it will be. We therefore do not directly know when a
22390  click outside the non-blocking popup must close it at that direct frame.
22391  Instead it will be closed in the next frame.*/
22392  struct nk_rect body = {0,0,0,0};
22393  if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
22394  struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
22395  body = panel->bounds;
22396  body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
22397  body.h = (panel->bounds.y + panel->bounds.h) - body.y;
22398  }
22399 
22400  {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
22401  int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22402  if (pressed && in_body)
22403  popup->flags |= NK_WINDOW_HIDDEN;
22404  }
22405  }
22406  if (popup->flags & NK_WINDOW_HIDDEN)
22407  popup->seq = 0;
22408  nk_popup_end(ctx);
22409  return;
22410 }
22411 /* -------------------------------------------------------------
22412  *
22413  * COMBO
22414  *
22415  * --------------------------------------------------------------*/
22416 NK_INTERN int
22417 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
22418  struct nk_vec2 size, int is_clicked, struct nk_rect header)
22419 {
22420  struct nk_window *popup;
22421  int is_open = 0;
22422  int is_active = 0;
22423  struct nk_rect body;
22424  nk_hash hash;
22425 
22426  NK_ASSERT(ctx);
22427  NK_ASSERT(ctx->current);
22428  NK_ASSERT(ctx->current->layout);
22429  if (!ctx || !ctx->current || !ctx->current->layout)
22430  return 0;
22431 
22432  popup = win->popup.win;
22433  body.x = header.x;
22434  body.w = size.x;
22435  body.y = header.y + header.h-ctx->style.window.combo_border;
22436  body.h = size.y;
22437 
22438  hash = win->popup.combo_count++;
22439  is_open = (popup) ? nk_true:nk_false;
22440  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
22441  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
22442  (!is_open && !is_active && !is_clicked)) return 0;
22443  if (!nk_nonblock_begin(ctx, 0, body,
22444  (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
22445 
22446  win->popup.type = NK_PANEL_COMBO;
22447  win->popup.name = hash;
22448  return 1;
22449 }
22450 
22451 NK_API int
22452 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
22453  struct nk_vec2 size)
22454 {
22455  const struct nk_input *in;
22456  struct nk_window *win;
22457  struct nk_style *style;
22458 
22459  enum nk_widget_layout_states s;
22460  int is_clicked = nk_false;
22461  struct nk_rect header;
22462  const struct nk_style_item *background;
22463  struct nk_text text;
22464 
22465  NK_ASSERT(ctx);
22466  NK_ASSERT(selected);
22467  NK_ASSERT(ctx->current);
22468  NK_ASSERT(ctx->current->layout);
22469  if (!ctx || !ctx->current || !ctx->current->layout || !selected)
22470  return 0;
22471 
22472  win = ctx->current;
22473  style = &ctx->style;
22474  s = nk_widget(&header, ctx);
22475  if (s == NK_WIDGET_INVALID)
22476  return 0;
22477 
22478  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22479  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22480  is_clicked = nk_true;
22481 
22482  /* draw combo box header background and border */
22483  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22484  background = &style->combo.active;
22485  text.text = style->combo.label_active;
22486  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22487  background = &style->combo.hover;
22488  text.text = style->combo.label_hover;
22489  } else {
22490  background = &style->combo.normal;
22491  text.text = style->combo.label_normal;
22492  }
22493  if (background->type == NK_STYLE_ITEM_IMAGE) {
22494  text.background = nk_rgba(0,0,0,0);
22495  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22496  } else {
22497  text.background = background->data.color;
22498  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22499  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22500  }
22501  {
22502  /* print currently selected text item */
22503  struct nk_rect label;
22504  struct nk_rect button;
22505  struct nk_rect content;
22506 
22507  enum nk_symbol_type sym;
22508  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22509  sym = style->combo.sym_hover;
22510  else if (is_clicked)
22511  sym = style->combo.sym_active;
22512  else sym = style->combo.sym_normal;
22513 
22514  /* calculate button */
22515  button.w = header.h - 2 * style->combo.button_padding.y;
22516  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22517  button.y = header.y + style->combo.button_padding.y;
22518  button.h = button.w;
22519 
22520  content.x = button.x + style->combo.button.padding.x;
22521  content.y = button.y + style->combo.button.padding.y;
22522  content.w = button.w - 2 * style->combo.button.padding.x;
22523  content.h = button.h - 2 * style->combo.button.padding.y;
22524 
22525  /* draw selected label */
22526  text.padding = nk_vec2(0,0);
22527  label.x = header.x + style->combo.content_padding.x;
22528  label.y = header.y + style->combo.content_padding.y;
22529  label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
22530  label.h = header.h - 2 * style->combo.content_padding.y;
22531  nk_widget_text(&win->buffer, label, selected, len, &text,
22532  NK_TEXT_LEFT, ctx->style.font);
22533 
22534  /* draw open/close button */
22535  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22536  &ctx->style.combo.button, sym, style->font);
22537  }
22538  return nk_combo_begin(ctx, win, size, is_clicked, header);
22539 }
22540 
22541 NK_API int nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
22542 {return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);}
22543 
22544 NK_API int
22545 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
22546 {
22547  struct nk_window *win;
22548  struct nk_style *style;
22549  const struct nk_input *in;
22550 
22551  struct nk_rect header;
22552  int is_clicked = nk_false;
22553  enum nk_widget_layout_states s;
22554  const struct nk_style_item *background;
22555 
22556  NK_ASSERT(ctx);
22557  NK_ASSERT(ctx->current);
22558  NK_ASSERT(ctx->current->layout);
22559  if (!ctx || !ctx->current || !ctx->current->layout)
22560  return 0;
22561 
22562  win = ctx->current;
22563  style = &ctx->style;
22564  s = nk_widget(&header, ctx);
22565  if (s == NK_WIDGET_INVALID)
22566  return 0;
22567 
22568  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22569  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22570  is_clicked = nk_true;
22571 
22572  /* draw combo box header background and border */
22573  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
22574  background = &style->combo.active;
22575  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22576  background = &style->combo.hover;
22577  else background = &style->combo.normal;
22578 
22579  if (background->type == NK_STYLE_ITEM_IMAGE) {
22580  nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
22581  } else {
22582  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22583  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22584  }
22585  {
22586  struct nk_rect content;
22587  struct nk_rect button;
22588  struct nk_rect bounds;
22589 
22590  enum nk_symbol_type sym;
22591  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22592  sym = style->combo.sym_hover;
22593  else if (is_clicked)
22594  sym = style->combo.sym_active;
22595  else sym = style->combo.sym_normal;
22596 
22597  /* calculate button */
22598  button.w = header.h - 2 * style->combo.button_padding.y;
22599  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22600  button.y = header.y + style->combo.button_padding.y;
22601  button.h = button.w;
22602 
22603  content.x = button.x + style->combo.button.padding.x;
22604  content.y = button.y + style->combo.button.padding.y;
22605  content.w = button.w - 2 * style->combo.button.padding.x;
22606  content.h = button.h - 2 * style->combo.button.padding.y;
22607 
22608  /* draw color */
22609  bounds.h = header.h - 4 * style->combo.content_padding.y;
22610  bounds.y = header.y + 2 * style->combo.content_padding.y;
22611  bounds.x = header.x + 2 * style->combo.content_padding.x;
22612  bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
22613  nk_fill_rect(&win->buffer, bounds, 0, color);
22614 
22615  /* draw open/close button */
22616  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22617  &ctx->style.combo.button, sym, style->font);
22618  }
22619  return nk_combo_begin(ctx, win, size, is_clicked, header);
22620 }
22621 
22622 NK_API int
22623 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
22624 {
22625  struct nk_window *win;
22626  struct nk_style *style;
22627  const struct nk_input *in;
22628 
22629  struct nk_rect header;
22630  int is_clicked = nk_false;
22631  enum nk_widget_layout_states s;
22632  const struct nk_style_item *background;
22633  struct nk_color sym_background;
22634  struct nk_color symbol_color;
22635 
22636  NK_ASSERT(ctx);
22637  NK_ASSERT(ctx->current);
22638  NK_ASSERT(ctx->current->layout);
22639  if (!ctx || !ctx->current || !ctx->current->layout)
22640  return 0;
22641 
22642  win = ctx->current;
22643  style = &ctx->style;
22644  s = nk_widget(&header, ctx);
22645  if (s == NK_WIDGET_INVALID)
22646  return 0;
22647 
22648  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22649  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22650  is_clicked = nk_true;
22651 
22652  /* draw combo box header background and border */
22653  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22654  background = &style->combo.active;
22655  symbol_color = style->combo.symbol_active;
22656  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22657  background = &style->combo.hover;
22658  symbol_color = style->combo.symbol_hover;
22659  } else {
22660  background = &style->combo.normal;
22661  symbol_color = style->combo.symbol_hover;
22662  }
22663 
22664  if (background->type == NK_STYLE_ITEM_IMAGE) {
22665  sym_background = nk_rgba(0,0,0,0);
22666  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22667  } else {
22668  sym_background = background->data.color;
22669  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22670  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22671  }
22672  {
22673  struct nk_rect bounds = {0,0,0,0};
22674  struct nk_rect content;
22675  struct nk_rect button;
22676 
22677  enum nk_symbol_type sym;
22678  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22679  sym = style->combo.sym_hover;
22680  else if (is_clicked)
22681  sym = style->combo.sym_active;
22682  else sym = style->combo.sym_normal;
22683 
22684  /* calculate button */
22685  button.w = header.h - 2 * style->combo.button_padding.y;
22686  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
22687  button.y = header.y + style->combo.button_padding.y;
22688  button.h = button.w;
22689 
22690  content.x = button.x + style->combo.button.padding.x;
22691  content.y = button.y + style->combo.button.padding.y;
22692  content.w = button.w - 2 * style->combo.button.padding.x;
22693  content.h = button.h - 2 * style->combo.button.padding.y;
22694 
22695  /* draw symbol */
22696  bounds.h = header.h - 2 * style->combo.content_padding.y;
22697  bounds.y = header.y + style->combo.content_padding.y;
22698  bounds.x = header.x + style->combo.content_padding.x;
22699  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
22700  nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
22701  1.0f, style->font);
22702 
22703  /* draw open/close button */
22704  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
22705  &ctx->style.combo.button, sym, style->font);
22706  }
22707  return nk_combo_begin(ctx, win, size, is_clicked, header);
22708 }
22709 
22710 NK_API int
22711 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
22712  enum nk_symbol_type symbol, struct nk_vec2 size)
22713 {
22714  struct nk_window *win;
22715  struct nk_style *style;
22716  struct nk_input *in;
22717 
22718  struct nk_rect header;
22719  int is_clicked = nk_false;
22720  enum nk_widget_layout_states s;
22721  const struct nk_style_item *background;
22722  struct nk_color symbol_color;
22723  struct nk_text text;
22724 
22725  NK_ASSERT(ctx);
22726  NK_ASSERT(ctx->current);
22727  NK_ASSERT(ctx->current->layout);
22728  if (!ctx || !ctx->current || !ctx->current->layout)
22729  return 0;
22730 
22731  win = ctx->current;
22732  style = &ctx->style;
22733  s = nk_widget(&header, ctx);
22734  if (!s) return 0;
22735 
22736  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22737  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22738  is_clicked = nk_true;
22739 
22740  /* draw combo box header background and border */
22741  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22742  background = &style->combo.active;
22743  symbol_color = style->combo.symbol_active;
22744  text.text = style->combo.label_active;
22745  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22746  background = &style->combo.hover;
22747  symbol_color = style->combo.symbol_hover;
22748  text.text = style->combo.label_hover;
22749  } else {
22750  background = &style->combo.normal;
22751  symbol_color = style->combo.symbol_normal;
22752  text.text = style->combo.label_normal;
22753  }
22754  if (background->type == NK_STYLE_ITEM_IMAGE) {
22755  text.background = nk_rgba(0,0,0,0);
22756  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22757  } else {
22758  text.background = background->data.color;
22759  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22760  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22761  }
22762  {
22763  struct nk_rect content;
22764  struct nk_rect button;
22765  struct nk_rect label;
22766  struct nk_rect image;
22767 
22768  enum nk_symbol_type sym;
22769  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22770  sym = style->combo.sym_hover;
22771  else if (is_clicked)
22772  sym = style->combo.sym_active;
22773  else sym = style->combo.sym_normal;
22774 
22775  /* calculate button */
22776  button.w = header.h - 2 * style->combo.button_padding.y;
22777  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22778  button.y = header.y + style->combo.button_padding.y;
22779  button.h = button.w;
22780 
22781  content.x = button.x + style->combo.button.padding.x;
22782  content.y = button.y + style->combo.button.padding.y;
22783  content.w = button.w - 2 * style->combo.button.padding.x;
22784  content.h = button.h - 2 * style->combo.button.padding.y;
22785  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22786  &ctx->style.combo.button, sym, style->font);
22787 
22788  /* draw symbol */
22789  image.x = header.x + style->combo.content_padding.x;
22790  image.y = header.y + style->combo.content_padding.y;
22791  image.h = header.h - 2 * style->combo.content_padding.y;
22792  image.w = image.h;
22793  nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
22794  1.0f, style->font);
22795 
22796  /* draw label */
22797  text.padding = nk_vec2(0,0);
22798  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
22799  label.y = header.y + style->combo.content_padding.y;
22800  label.w = (button.x - style->combo.content_padding.x) - label.x;
22801  label.h = header.h - 2 * style->combo.content_padding.y;
22802  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
22803  }
22804  return nk_combo_begin(ctx, win, size, is_clicked, header);
22805 }
22806 
22807 NK_API int
22808 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
22809 {
22810  struct nk_window *win;
22811  struct nk_style *style;
22812  const struct nk_input *in;
22813 
22814  struct nk_rect header;
22815  int is_clicked = nk_false;
22816  enum nk_widget_layout_states s;
22817  const struct nk_style_item *background;
22818 
22819  NK_ASSERT(ctx);
22820  NK_ASSERT(ctx->current);
22821  NK_ASSERT(ctx->current->layout);
22822  if (!ctx || !ctx->current || !ctx->current->layout)
22823  return 0;
22824 
22825  win = ctx->current;
22826  style = &ctx->style;
22827  s = nk_widget(&header, ctx);
22828  if (s == NK_WIDGET_INVALID)
22829  return 0;
22830 
22831  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22832  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22833  is_clicked = nk_true;
22834 
22835  /* draw combo box header background and border */
22836  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
22837  background = &style->combo.active;
22838  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22839  background = &style->combo.hover;
22840  else background = &style->combo.normal;
22841 
22842  if (background->type == NK_STYLE_ITEM_IMAGE) {
22843  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22844  } else {
22845  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22846  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22847  }
22848  {
22849  struct nk_rect bounds = {0,0,0,0};
22850  struct nk_rect content;
22851  struct nk_rect button;
22852 
22853  enum nk_symbol_type sym;
22854  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22855  sym = style->combo.sym_hover;
22856  else if (is_clicked)
22857  sym = style->combo.sym_active;
22858  else sym = style->combo.sym_normal;
22859 
22860  /* calculate button */
22861  button.w = header.h - 2 * style->combo.button_padding.y;
22862  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
22863  button.y = header.y + style->combo.button_padding.y;
22864  button.h = button.w;
22865 
22866  content.x = button.x + style->combo.button.padding.x;
22867  content.y = button.y + style->combo.button.padding.y;
22868  content.w = button.w - 2 * style->combo.button.padding.x;
22869  content.h = button.h - 2 * style->combo.button.padding.y;
22870 
22871  /* draw image */
22872  bounds.h = header.h - 2 * style->combo.content_padding.y;
22873  bounds.y = header.y + style->combo.content_padding.y;
22874  bounds.x = header.x + style->combo.content_padding.x;
22875  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
22876  nk_draw_image(&win->buffer, bounds, &img, nk_white);
22877 
22878  /* draw open/close button */
22879  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
22880  &ctx->style.combo.button, sym, style->font);
22881  }
22882  return nk_combo_begin(ctx, win, size, is_clicked, header);
22883 }
22884 
22885 NK_API int
22886 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
22887  struct nk_image img, struct nk_vec2 size)
22888 {
22889  struct nk_window *win;
22890  struct nk_style *style;
22891  struct nk_input *in;
22892 
22893  struct nk_rect header;
22894  int is_clicked = nk_false;
22895  enum nk_widget_layout_states s;
22896  const struct nk_style_item *background;
22897  struct nk_text text;
22898 
22899  NK_ASSERT(ctx);
22900  NK_ASSERT(ctx->current);
22901  NK_ASSERT(ctx->current->layout);
22902  if (!ctx || !ctx->current || !ctx->current->layout)
22903  return 0;
22904 
22905  win = ctx->current;
22906  style = &ctx->style;
22907  s = nk_widget(&header, ctx);
22908  if (!s) return 0;
22909 
22910  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22911  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22912  is_clicked = nk_true;
22913 
22914  /* draw combo box header background and border */
22915  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22916  background = &style->combo.active;
22917  text.text = style->combo.label_active;
22918  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22919  background = &style->combo.hover;
22920  text.text = style->combo.label_hover;
22921  } else {
22922  background = &style->combo.normal;
22923  text.text = style->combo.label_normal;
22924  }
22925  if (background->type == NK_STYLE_ITEM_IMAGE) {
22926  text.background = nk_rgba(0,0,0,0);
22927  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22928  } else {
22929  text.background = background->data.color;
22930  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22931  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22932  }
22933  {
22934  struct nk_rect content;
22935  struct nk_rect button;
22936  struct nk_rect label;
22937  struct nk_rect image;
22938 
22939  enum nk_symbol_type sym;
22940  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22941  sym = style->combo.sym_hover;
22942  else if (is_clicked)
22943  sym = style->combo.sym_active;
22944  else sym = style->combo.sym_normal;
22945 
22946  /* calculate button */
22947  button.w = header.h - 2 * style->combo.button_padding.y;
22948  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22949  button.y = header.y + style->combo.button_padding.y;
22950  button.h = button.w;
22951 
22952  content.x = button.x + style->combo.button.padding.x;
22953  content.y = button.y + style->combo.button.padding.y;
22954  content.w = button.w - 2 * style->combo.button.padding.x;
22955  content.h = button.h - 2 * style->combo.button.padding.y;
22956  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22957  &ctx->style.combo.button, sym, style->font);
22958 
22959  /* draw image */
22960  image.x = header.x + style->combo.content_padding.x;
22961  image.y = header.y + style->combo.content_padding.y;
22962  image.h = header.h - 2 * style->combo.content_padding.y;
22963  image.w = image.h;
22964  nk_draw_image(&win->buffer, image, &img, nk_white);
22965 
22966  /* draw label */
22967  text.padding = nk_vec2(0,0);
22968  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
22969  label.y = header.y + style->combo.content_padding.y;
22970  label.w = (button.x - style->combo.content_padding.x) - label.x;
22971  label.h = header.h - 2 * style->combo.content_padding.y;
22972  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
22973  }
22974  return nk_combo_begin(ctx, win, size, is_clicked, header);
22975 }
22976 
22978  const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
22979 {return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);}
22980 
22982  const char *selected, struct nk_image img, struct nk_vec2 size)
22983 {return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);}
22984 
22985 NK_API int nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
22986 {return nk_contextual_item_text(ctx, text, len, align);}
22987 
22988 NK_API int nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
22989 {return nk_contextual_item_label(ctx, label, align);}
22990 
22991 NK_API int nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
22992  int len, nk_flags alignment)
22993 {return nk_contextual_item_image_text(ctx, img, text, len, alignment);}
22994 
22995 NK_API int nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
22996  const char *text, nk_flags alignment)
22997 {return nk_contextual_item_image_label(ctx, img, text, alignment);}
22998 
22999 NK_API int nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
23000  const char *text, int len, nk_flags alignment)
23001 {return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);}
23002 
23004  const char *label, nk_flags alignment)
23005 {return nk_contextual_item_symbol_label(ctx, sym, label, alignment);}
23006 
23007 NK_API void nk_combo_end(struct nk_context *ctx)
23008 {nk_contextual_end(ctx);}
23009 
23010 NK_API void nk_combo_close(struct nk_context *ctx)
23011 {nk_contextual_close(ctx);}
23012 
23013 NK_API int
23014 nk_combo(struct nk_context *ctx, const char **items, int count,
23015  int selected, int item_height, struct nk_vec2 size)
23016 {
23017  int i = 0;
23018  int max_height;
23019  struct nk_vec2 item_spacing;
23020  struct nk_vec2 window_padding;
23021 
23022  NK_ASSERT(ctx);
23023  NK_ASSERT(items);
23024  NK_ASSERT(ctx->current);
23025  if (!ctx || !items ||!count)
23026  return selected;
23027 
23028  item_spacing = ctx->style.window.spacing;
23029  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23030  max_height = count * item_height + count * (int)item_spacing.y;
23031  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23032  size.y = NK_MIN(size.y, (float)max_height);
23033  if (nk_combo_begin_label(ctx, items[selected], size)) {
23034  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23035  for (i = 0; i < count; ++i) {
23036  if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
23037  selected = i;
23038  }
23039  nk_combo_end(ctx);
23040  }
23041  return selected;
23042 }
23043 
23044 NK_API int
23045 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23046  int separator, int selected, int count, int item_height, struct nk_vec2 size)
23047 {
23048  int i;
23049  int max_height;
23050  struct nk_vec2 item_spacing;
23051  struct nk_vec2 window_padding;
23052  const char *current_item;
23053  const char *iter;
23054  int length = 0;
23055 
23056  NK_ASSERT(ctx);
23057  NK_ASSERT(items_separated_by_separator);
23058  if (!ctx || !items_separated_by_separator)
23059  return selected;
23060 
23061  /* calculate popup window */
23062  item_spacing = ctx->style.window.spacing;
23063  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23064  max_height = count * item_height + count * (int)item_spacing.y;
23065  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23066  size.y = NK_MIN(size.y, (float)max_height);
23067 
23068  /* find selected item */
23069  current_item = items_separated_by_separator;
23070  for (i = 0; i < count; ++i) {
23071  iter = current_item;
23072  while (*iter && *iter != separator) iter++;
23073  length = (int)(iter - current_item);
23074  if (i == selected) break;
23075  current_item = iter + 1;
23076  }
23077 
23078  if (nk_combo_begin_text(ctx, current_item, length, size)) {
23079  current_item = items_separated_by_separator;
23080  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23081  for (i = 0; i < count; ++i) {
23082  iter = current_item;
23083  while (*iter && *iter != separator) iter++;
23084  length = (int)(iter - current_item);
23085  if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
23086  selected = i;
23087  current_item = current_item + length + 1;
23088  }
23089  nk_combo_end(ctx);
23090  }
23091  return selected;
23092 }
23093 
23094 NK_API int
23095 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23096  int selected, int count, int item_height, struct nk_vec2 size)
23097 {return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);}
23098 
23099 NK_API int
23100 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
23101  void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
23102 {
23103  int i;
23104  int max_height;
23105  struct nk_vec2 item_spacing;
23106  struct nk_vec2 window_padding;
23107  const char *item;
23108 
23109  NK_ASSERT(ctx);
23110  NK_ASSERT(item_getter);
23111  if (!ctx || !item_getter)
23112  return selected;
23113 
23114  /* calculate popup window */
23115  item_spacing = ctx->style.window.spacing;
23116  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23117  max_height = count * item_height + count * (int)item_spacing.y;
23118  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23119  size.y = NK_MIN(size.y, (float)max_height);
23120 
23121  item_getter(userdata, selected, &item);
23122  if (nk_combo_begin_label(ctx, item, size)) {
23123  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23124  for (i = 0; i < count; ++i) {
23125  item_getter(userdata, i, &item);
23126  if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
23127  selected = i;
23128  }
23129  nk_combo_end(ctx);
23130  }
23131  return selected;
23132 }
23133 
23134 NK_API void nk_combobox(struct nk_context *ctx, const char **items, int count,
23135  int *selected, int item_height, struct nk_vec2 size)
23136 {*selected = nk_combo(ctx, items, count, *selected, item_height, size);}
23137 
23138 NK_API void nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23139  int *selected, int count, int item_height, struct nk_vec2 size)
23140 {*selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);}
23141 
23142 NK_API void nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23143  int separator,int *selected, int count, int item_height, struct nk_vec2 size)
23144 {*selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
23145  *selected, count, item_height, size);}
23146 
23147 NK_API void nk_combobox_callback(struct nk_context *ctx,
23148  void(*item_getter)(void* data, int id, const char **out_text),
23149  void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
23150 {*selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);}
23151 
23152 /*
23153  * -------------------------------------------------------------
23154  *
23155  * MENU
23156  *
23157  * --------------------------------------------------------------
23158  */
23159 NK_INTERN int
23160 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
23161  const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
23162 {
23163  int is_open = 0;
23164  int is_active = 0;
23165  struct nk_rect body;
23166  struct nk_window *popup;
23167  nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
23168 
23169  NK_ASSERT(ctx);
23170  NK_ASSERT(ctx->current);
23171  NK_ASSERT(ctx->current->layout);
23172  if (!ctx || !ctx->current || !ctx->current->layout)
23173  return 0;
23174 
23175  body.x = header.x;
23176  body.w = size.x;
23177  body.y = header.y + header.h;
23178  body.h = size.y;
23179 
23180  popup = win->popup.win;
23181  is_open = popup ? nk_true : nk_false;
23182  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
23183  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
23184  (!is_open && !is_active && !is_clicked)) return 0;
23185  if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
23186  return 0;
23187 
23188  win->popup.type = NK_PANEL_MENU;
23189  win->popup.name = hash;
23190  return 1;
23191 }
23192 
23193 NK_API int
23194 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
23195  nk_flags align, struct nk_vec2 size)
23196 {
23197  struct nk_window *win;
23198  const struct nk_input *in;
23199  struct nk_rect header;
23200  int is_clicked = nk_false;
23201  nk_flags state;
23202 
23203  NK_ASSERT(ctx);
23204  NK_ASSERT(ctx->current);
23205  NK_ASSERT(ctx->current->layout);
23206  if (!ctx || !ctx->current || !ctx->current->layout)
23207  return 0;
23208 
23209  win = ctx->current;
23210  state = nk_widget(&header, ctx);
23211  if (!state) return 0;
23212  in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23213  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
23214  title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23215  is_clicked = nk_true;
23216  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23217 }
23218 
23219 NK_API int nk_menu_begin_label(struct nk_context *ctx,
23220  const char *text, nk_flags align, struct nk_vec2 size)
23221 {return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);}
23222 
23223 NK_API int
23224 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
23225  struct nk_vec2 size)
23226 {
23227  struct nk_window *win;
23228  struct nk_rect header;
23229  const struct nk_input *in;
23230  int is_clicked = nk_false;
23231  nk_flags state;
23232 
23233  NK_ASSERT(ctx);
23234  NK_ASSERT(ctx->current);
23235  NK_ASSERT(ctx->current->layout);
23236  if (!ctx || !ctx->current || !ctx->current->layout)
23237  return 0;
23238 
23239  win = ctx->current;
23240  state = nk_widget(&header, ctx);
23241  if (!state) return 0;
23242  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23243  if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
23244  img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
23245  is_clicked = nk_true;
23246  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23247 }
23248 
23249 NK_API int
23250 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
23251  enum nk_symbol_type sym, struct nk_vec2 size)
23252 {
23253  struct nk_window *win;
23254  const struct nk_input *in;
23255  struct nk_rect header;
23256  int is_clicked = nk_false;
23257  nk_flags state;
23258 
23259  NK_ASSERT(ctx);
23260  NK_ASSERT(ctx->current);
23261  NK_ASSERT(ctx->current->layout);
23262  if (!ctx || !ctx->current || !ctx->current->layout)
23263  return 0;
23264 
23265  win = ctx->current;
23266  state = nk_widget(&header, ctx);
23267  if (!state) return 0;
23268  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23269  if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header,
23270  sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23271  is_clicked = nk_true;
23272  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23273 }
23274 
23275 NK_API int
23276 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
23277  nk_flags align, struct nk_image img, struct nk_vec2 size)
23278 {
23279  struct nk_window *win;
23280  struct nk_rect header;
23281  const struct nk_input *in;
23282  int is_clicked = nk_false;
23283  nk_flags state;
23284 
23285  NK_ASSERT(ctx);
23286  NK_ASSERT(ctx->current);
23287  NK_ASSERT(ctx->current->layout);
23288  if (!ctx || !ctx->current || !ctx->current->layout)
23289  return 0;
23290 
23291  win = ctx->current;
23292  state = nk_widget(&header, ctx);
23293  if (!state) return 0;
23294  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23295  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
23296  header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23297  ctx->style.font, in))
23298  is_clicked = nk_true;
23299  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23300 }
23301 
23303  const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
23304 {return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);}
23305 
23306 NK_API int
23307 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
23308  nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
23309 {
23310  struct nk_window *win;
23311  struct nk_rect header;
23312  const struct nk_input *in;
23313  int is_clicked = nk_false;
23314  nk_flags state;
23315 
23316  NK_ASSERT(ctx);
23317  NK_ASSERT(ctx->current);
23318  NK_ASSERT(ctx->current->layout);
23319  if (!ctx || !ctx->current || !ctx->current->layout)
23320  return 0;
23321 
23322  win = ctx->current;
23323  state = nk_widget(&header, ctx);
23324  if (!state) return 0;
23325 
23326  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23327  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
23328  header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23329  ctx->style.font, in)) is_clicked = nk_true;
23330  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23331 }
23332 
23334  const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
23335 {return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);}
23336 
23337 NK_API int nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
23338 {return nk_contextual_item_text(ctx, title, len, align);}
23339 
23340 NK_API int nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
23341 {return nk_contextual_item_label(ctx, label, align);}
23342 
23343 NK_API int nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
23344  const char *label, nk_flags align)
23345 {return nk_contextual_item_image_label(ctx, img, label, align);}
23346 
23347 NK_API int nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
23348  const char *text, int len, nk_flags align)
23349 {return nk_contextual_item_image_text(ctx, img, text, len, align);}
23350 
23351 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
23352  const char *text, int len, nk_flags align)
23353 {return nk_contextual_item_symbol_text(ctx, sym, text, len, align);}
23354 
23355 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
23356  const char *label, nk_flags align)
23357 {return nk_contextual_item_symbol_label(ctx, sym, label, align);}
23358 
23359 NK_API void nk_menu_close(struct nk_context *ctx)
23360 {nk_contextual_close(ctx);}
23361 
23362 NK_API void
23363 nk_menu_end(struct nk_context *ctx)
23364 {nk_contextual_end(ctx);}
23365 
23366 #endif
Definition: nuklear.h:1902
unsigned short r
Definition: nuklear.h:2944
struct nk_vec2 padding
Definition: nuklear.h:3507
Definition: nuklear.h:3007
Definition: nuklear.h:2027
NK_API struct nk_color nk_rgb_iv(const int *rgb)
struct nk_command header
Definition: nuklear.h:2857
Definition: nuklear.h:689
short cx
Definition: nuklear.h:2943
NK_API int nk_menu_item_text(struct nk_context *, const char *, int, nk_flags align)
struct nk_style_item hover
Definition: nuklear.h:3457
nk_chart_event
Definition: nuklear.h:472
struct nk_vec2 padding
Definition: nuklear.h:3413
float preferred_x
Definition: nuklear.h:2741
struct nk_style_item hover_active
Definition: nuklear.h:3329
NK_API int nk_window_has_focus(const struct nk_context *)
NK_API int nk_menu_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
Definition: nuklear.h:3726
struct nk_style_button dec_button
Definition: nuklear.h:3511
NK_API struct nk_rect nk_rectv(const float *xywh)
nk_handle userdata
Definition: nuklear.h:3416
Definition: nuklear.h:1890
#define NK_CONFIG_STACK(type, size)
Definition: nuklear.h:3930
struct nk_style_item cursor_hover
Definition: nuklear.h:3300
struct nk_command header
Definition: nuklear.h:2910
NK_API int nk_input_mouse_clicked(const struct nk_input *, enum nk_buttons, struct nk_rect)
struct nk_pool pool
Definition: nuklear.h:4036
struct nk_style_item active
Definition: nuklear.h:3360
NK_API int nk_select_text(struct nk_context *, const char *, int, nk_flags align, int value)
NK_API int nk_tree_state_image_push(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state)
unsigned int scrolled
Definition: nuklear.h:3860
NK_API void nk_window_set_position(struct nk_context *, struct nk_vec2 pos)
NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba)
float menu_border
Definition: nuklear.h:3631
NK_API int nk_contextual_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
NK_API void nk_textedit_select_all(struct nk_text_edit *)
struct nk_style_button close_button
Definition: nuklear.h:3596
Definition: nuklear.h:2941
nk_convert_result
Definition: nuklear.h:970
NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align)
NK_API int nk_contextual_begin(struct nk_context *, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds)
struct nk_vec2 last
Definition: nuklear.h:3711
struct nk_color label_normal
Definition: nuklear.h:3603
struct nk_color text_hover
Definition: nuklear.h:3334
Definition: nuklear.h:3705
Definition: nuklear.h:2932
int show_buttons
Definition: nuklear.h:3442
void * memory
Definition: nuklear.h:2538
struct nk_style_item cursor_normal
Definition: nuklear.h:3299
Definition: nuklear.h:3044
NK_API void nk_color_hex_rgb(char *output, struct nk_color)
float rounding_cursor
Definition: nuklear.h:3438
Definition: nuklear.h:2041
float border
Definition: nuklear.h:3279
float border
Definition: nuklear.h:3770
NK_API struct nk_rect nk_get_null_rect(void)
nk_buffer_allocation_type
Definition: nuklear.h:2551
NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags)
void *(* nk_plugin_alloc)(nk_handle, void *old, nk_size)
Definition: nuklear.h:478
struct nk_color color
Definition: nuklear.h:2946
#define NK_STORAGE
Definition: nuklear.h:287
nk_handle userdata
Definition: nuklear.h:3390
nk_widget_states
Definition: nuklear.h:1714
void(* nk_plugin_paste)(nk_handle, struct nk_text_edit *)
Definition: nuklear.h:481
Definition: nuklear.h:1184
float tooltip_border
Definition: nuklear.h:3633
float max_x
Definition: nuklear.h:3767
#define NK_INT32
Definition: nuklear.h:352
NK_API int nk_contextual_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_filter_default(const struct nk_text_edit *, nk_rune unicode)
unsigned int page_count
Definition: nuklear.h:3997
nk_size allocated
Definition: nuklear.h:2574
unsigned short w
Definition: nuklear.h:2893
NK_API int nk_widget_is_mouse_click_down(struct nk_context *, enum nk_buttons, int down)
NK_API void nk_stroke_circle(struct nk_command_buffer *, struct nk_rect, float line_thickness, struct nk_color)
NK_API struct nk_vec2 nk_vec2i(int x, int y)
Definition: nuklear.h:1183
struct nk_vec2 contextual_padding
Definition: nuklear.h:3645
Definition: nuklear.h:2042
nk_panel_flags
Definition: nuklear.h:1173
NK_API int nk_utf_decode(const char *, nk_rune *, int)
struct nk_style_button menu_button
Definition: nuklear.h:3660
Definition: nuklear.h:1896
NK_API struct nk_color nk_rgba_u32(nk_uint)
nk_size needed
Definition: nuklear.h:2576
NK_API int nk_filter_hex(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_menu_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
float bar_height
Definition: nuklear.h:3377
unsigned short w
Definition: nuklear.h:2886
NK_API void nk_buffer_init(struct nk_buffer *, const struct nk_allocator *, nk_size size)
NK_API int nk_button_color(struct nk_context *, struct nk_color)
unsigned short h
Definition: nuklear.h:2928
NK_API int nk_select_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int value)
NK_API struct nk_window * nk_window_find(struct nk_context *ctx, const char *name)
NK_API void nk_str_remove_chars(struct nk_str *, int len)
NK_API int nk_widget_is_hovered(struct nk_context *)
#define NK_FLAGS_STACK_SIZE
Definition: nuklear.h:3918
NK_API void nk_layout_row_end(struct nk_context *)
Definition: nuklear.h:2820
Definition: nuklear.h:664
NK_API void nk_fill_circle(struct nk_command_buffer *, struct nk_rect, struct nk_color)
NK_API void nk_window_set_size(struct nk_context *, struct nk_vec2)
struct nk_vec2 padding
Definition: nuklear.h:3261
#define nk_zero_struct(s)
Definition: nuklear.h:4072
struct nk_color label_active
Definition: nuklear.h:3605
struct nk_image img
Definition: nuklear.h:462
Definition: nuklear.h:3800
Definition: deflate.c:117
struct nk_color text_normal
Definition: nuklear.h:3273
Definition: nuklear.h:2553
nk_handle handle
Definition: nuklear.h:461
float border
Definition: nuklear.h:3505
Definition: nuklear.h:453
unsigned int seq
Definition: nuklear.h:3820
Definition: nuklear.h:3070
float rounding
Definition: nuklear.h:3436
Definition: nuklear.h:3697
short x
Definition: nuklear.h:2852
enum nk_symbol_type sym_left
Definition: nuklear.h:3501
struct nk_config_stack_button_behavior button_behaviors
Definition: nuklear.h:3960
nk_flags text_alignment
Definition: nuklear.h:3276
struct nk_rect clip
Definition: nuklear.h:3772
short y
Definition: nuklear.h:2892
struct config_s config
Definition: nuklear.h:670
nk_modify
Definition: nuklear.h:467
Definition: nuklear.h:484
struct nk_color selected_text_hover
Definition: nuklear.h:3477
NK_API int nk_combo_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down)
float y
Definition: nuklear.h:3757
short h
Definition: nuklear.h:458
NK_API void nk_str_init_fixed(struct nk_str *, void *memory, nk_size size)
Definition: nuklear.h:3818
struct nk_color col
Definition: nuklear.h:2977
NK_API int nk_popup_begin(struct nk_context *, enum nk_popup_type, const char *, nk_flags, struct nk_rect bounds)
NK_API void nk_property_float(struct nk_context *, const char *name, float min, float *val, float max, float step, float inc_per_pixel)
NK_API void nk_layout_row_template_push_variable(struct nk_context *, float min_width)
nk_style_header_align
Definition: nuklear.h:3585
struct nk_vec2 touch_padding
Definition: nuklear.h:3311
Definition: nuklear.h:1888
NK_API int nk_button_text_styled(struct nk_context *, const struct nk_style_button *, const char *title, int len)
struct nk_row_layout row
Definition: nuklear.h:3774
unsigned short line_thickness
Definition: nuklear.h:2967
unsigned int seq
Definition: nuklear.h:3970
struct nk_style_button node_maximize_button
Definition: nuklear.h:3572
NK_API void nk_layout_space_push(struct nk_context *, struct nk_rect)
NK_API void nk_layout_row_template_push_static(struct nk_context *, float width)
int cursor
Definition: nuklear.h:3835
NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color)
struct nk_vec2 tooltip_padding
Definition: nuklear.h:3647
Definition: nuklear.h:465
NK_API void nk_combobox_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *, int *selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_combo_item_text(struct nk_context *, const char *, int, nk_flags alignment)
Definition: nuklear.h:683
NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context *, nk_flags, char *buffer, int max, nk_plugin_filter)
struct nk_window * current
Definition: nuklear.h:4040
NK_API void nk_text(struct nk_context *, const char *, int, nk_flags)
nk_flags flags
Definition: nuklear.h:3848
Definition: nuklear.h:2833
Definition: nuklear.h:3693
struct nk_color color
Definition: nuklear.h:2914
Definition: nuklear.h:3702
Definition: nuklear.h:3994
nk_uint values[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:3972
Definition: nuklear.h:1879
float border
Definition: nuklear.h:3527
NK_API int nk_select_label(struct nk_context *, const char *, nk_flags align, int value)
float h
Definition: nuklear.h:3717
NK_API int nk_menu_item_label(struct nk_context *, const char *, nk_flags alignment)
struct nk_color color
Definition: nuklear.h:2861
Definition: nuklear.h:3730
float cursor_size
Definition: nuklear.h:3482
struct nk_vec2i c
Definition: nuklear.h:2905
struct nk_color selected_text_normal
Definition: nuklear.h:3476
Definition: nuklear.h:3519
float w
Definition: nuklear.h:3717
Definition: nuklear.h:1751
NK_API int nk_button_symbol_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type)
float item_height
Definition: nuklear.h:3740
struct nk_color color
Definition: nuklear.h:2870
struct nk_chart_slot slots[NK_CHART_MAX_SLOT]
Definition: nuklear.h:3718
float border
Definition: nuklear.h:3313
struct nk_color text_normal_active
Definition: nuklear.h:3338
char nk_glyph[NK_UTF_SIZE]
Definition: nuklear.h:459
nk_plugin_free free
Definition: nuklear.h:487
NK_POINTER_TYPE nk_ptr
Definition: nuklear.h:402
NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context *, struct nk_rect)
Definition: nuklear.h:492
nk_handle texture
Definition: nuklear.h:978
Definition: nuklear.h:1678
NK_API struct nk_color nk_hsv(int h, int s, int v)
struct nk_chart chart
Definition: nuklear.h:3775
struct nk_color tooltip_border_color
Definition: nuklear.h:3625
struct nk_vec2 image_padding
Definition: nuklear.h:3348
int where
Definition: nuklear.h:2699
nk_flags text_alignment
Definition: nuklear.h:3342
struct nk_vec2 cursor_size
Definition: nuklear.h:3380
struct nk_color group_border_color
Definition: nuklear.h:3624
struct nk_style_item scaler
Definition: nuklear.h:3626
Definition: nuklear.h:1174
#define NK_ABS(a)
Definition: nuklear.h:4056
nk_buttons
Definition: nuklear.h:695
NK_API void nk_edit_focus(struct nk_context *, nk_flags flags)
Definition: nuklear.h:3748
unsigned short point_count
Definition: nuklear.h:2953
Definition: nuklear.h:476
#define NK_MAX_FLOAT_PRECISION
Definition: nuklear.h:4051
#define NK_MAX_NUMBER_BUFFER
Definition: nuklear.h:260
unsigned char ungrab
Definition: nuklear.h:3057
short insert_length
Definition: nuklear.h:2700
short x
Definition: nuklear.h:2919
Definition: nuklear.h:3722
nk_edit_types
Definition: nuklear.h:1892
NK_API struct nk_color nk_hsv_fv(const float *hsv)
NK_API struct nk_style_item nk_style_item_image(struct nk_image img)
Definition: nuklear.h:1895
nk_anti_aliasing
Definition: nuklear.h:969
NK_API int nk_widget_is_mouse_clicked(struct nk_context *, enum nk_buttons)
struct nk_color bar_hover
Definition: nuklear.h:3365
struct nk_style_progress progress
Definition: nuklear.h:3665
NK_API void nk_window_collapse(struct nk_context *, const char *name, enum nk_collapse_states state)
Definition: nuklear.h:3691
short y
Definition: nuklear.h:458
Definition: nuklear.h:2055
NK_API void nk_button_set_behavior(struct nk_context *, enum nk_button_behavior)
nk_handle userdata
Definition: nuklear.h:2693
NK_API void nk_group_end(struct nk_context *)
NK_API int nk_input_is_key_pressed(const struct nk_input *, enum nk_keys)
unsigned short point_count
Definition: nuklear.h:2960
struct nk_style_item normal
Definition: nuklear.h:3323
#define NK_FLAG(x)
Definition: nuklear.h:290
unsigned short w
Definition: nuklear.h:2878
int32_t current
Definition: netobject.cpp:37
unsigned short line_thickness
Definition: nuklear.h:2858
#define NK_UTF_INVALID
Definition: nuklear.h:4050
unsigned short h
Definition: nuklear.h:2975
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3451
struct nk_color top
Definition: nuklear.h:2895
Definition: nuklear.h:3692
struct nk_property_state property
Definition: nuklear.h:3857
NK_API void nk_layout_space_end(struct nk_context *)
#define NK_GLOBAL
Definition: nuklear.h:288
struct nk_style_item active
Definition: nuklear.h:3458
struct nk_style_item cursor_hover
Definition: nuklear.h:3371
nk_flags flags
Definition: nuklear.h:3763
struct nk_color border_color
Definition: nuklear.h:3619
struct nk_color text_pressed
Definition: nuklear.h:3335
Definition: nuklear.h:1903
NK_API void nk_layout_row_template_push_dynamic(struct nk_context *)
short y
Definition: nuklear.h:2877
float min
Definition: nuklear.h:3709
unsigned short w
Definition: nuklear.h:2975
struct nk_style_item normal
Definition: nuklear.h:3266
struct nk_page_element * freelist
Definition: nuklear.h:4041
Definition: nuklear.h:2725
Definition: nuklear.h:2890
NK_API int k_button_symbol_label_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type, const char *, nk_flags text_alignment)
struct nk_vec2i c
Definition: nuklear.h:2913
struct nk_style_selectable selectable
Definition: nuklear.h:3663
NK_API int nk_str_insert_str_runes(struct nk_str *, int pos, const nk_rune *)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3515
enum nk_symbol_type sym_minimize
Definition: nuklear.h:3574
struct nk_style_button inc_button
Definition: nuklear.h:3384
nk_handle userdata
Definition: nuklear.h:3316
#define NK_ALIGNOF(t)
Definition: nuklear.h:4115
Definition: nuklear.h:969
struct nk_style_window window
Definition: nuklear.h:3673
float height
Definition: nuklear.h:3736
unsigned char grab
Definition: nuklear.h:3055
enum nk_symbol_type dec_symbol
Definition: nuklear.h:3446
int select_start
Definition: nuklear.h:2732
struct nk_vec2i ctrl[2]
Definition: nuklear.h:2869
float group_border
Definition: nuklear.h:3632
NK_API void nk_stroke_triangle(struct nk_command_buffer *, float, float, float, float, float, float, float line_thichness, struct nk_color)
NK_SIZE_TYPE nk_size
Definition: nuklear.h:401
unsigned short w
Definition: nuklear.h:2853
Definition: nuklear.h:3789
unsigned short line_thickness
Definition: nuklear.h:2902
struct nk_color border_color
Definition: nuklear.h:3459
struct nk_color text_normal
Definition: nuklear.h:3333
nk_panel_row_layout_type
Definition: nuklear.h:3721
struct nk_style_button contextual_button
Definition: nuklear.h:3659
Definition: nuklear.h:3060
NK_API void nk_label_wrap(struct nk_context *, const char *)
NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv)
Definition: nuklear.h:465
struct nk_style_item hover
Definition: nuklear.h:3267
NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score)
NK_API void nk_window_set_focus(struct nk_context *, const char *name)
Definition: nuklear.h:1175
Definition: nuklear.h:2031
NK_API void nk_str_delete_runes(struct nk_str *, int pos, int len)
struct nk_vec2 padding
Definition: nuklear.h:3439
#define NK_POINTER_TYPE
Definition: nuklear.h:389
Definition: nuklear.h:663
::std::string string
Definition: gtest-port.h:872
unsigned int seq
Definition: nuklear.h:3839
NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva)
#define SEEK_END
Definition: zconf.h:390
NK_API int nk_utf_encode(nk_rune, char *, int)
NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color)
nk_byte r
Definition: nuklear.h:453
float a[2]
Definition: nuklear.h:2937
Definition: nuklear.h:2720
NK_API int nk_str_append_text_char(struct nk_str *, const char *, int)
struct nk_color border_color
Definition: nuklear.h:3537
float rounding
Definition: nuklear.h:3280
NK_API void nk_fill_rect_multi_color(struct nk_command_buffer *, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom)
struct nk_memory memory
Definition: nuklear.h:2570
NK_API void nk_list_view_end(struct nk_list_view *)
struct nk_color color
Definition: nuklear.h:2966
float header_height
Definition: nuklear.h:3769
unsigned con_old
Definition: nuklear.h:3813
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3418
NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context *, struct nk_vec2)
struct nk_image img
Definition: nuklear.h:2976
nk_size begin
Definition: nuklear.h:3749
NK_API char * nk_str_at_rune(struct nk_str *, int pos, nk_rune *unicode, int *len)
struct nk_mouse_button buttons[NK_BUTTON_MAX]
Definition: nuklear.h:3050
struct nk_vec2 clicked_pos
Definition: nuklear.h:3047
Definition: nuklear.h:1722
unsigned char has_preferred_x
Definition: nuklear.h:2737
NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context *, struct nk_rect)
struct nk_window * parent
Definition: nuklear.h:3869
int index
Definition: nuklear.h:3735
Definition: nuklear.h:458
union nk_style_item_data data
Definition: nuklear.h:3256
float border
Definition: nuklear.h:3375
Definition: nuklear.h:691
NK_API nk_uint nk_color_u32(struct nk_color)
NK_API struct nk_vec2 nk_widget_position(struct nk_context *)
struct nk_color background
Definition: nuklear.h:3617
Definition: nuklear.h:463
NK_API int nk_button_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_filter_ascii(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:3695
struct nk_color bottom
Definition: nuklear.h:2896
nk_popup_type
Definition: nuklear.h:474
int prev
Definition: nuklear.h:3832
NK_API int nk_contextual_item_text(struct nk_context *, const char *, int, nk_flags align)
struct nk_page_element * next
Definition: nuklear.h:3984
nk_uint nk_flags
Definition: nuklear.h:405
float at_x
Definition: nuklear.h:3767
Definition: nuklear.h:3245
NK_API int nk_str_insert_text_char(struct nk_str *, int pos, const char *, int)
int count
Definition: nuklear.h:3710
struct nk_window * active
Definition: nuklear.h:4039
struct nk_color highlight
Definition: nuklear.h:3708
struct nk_color color
Definition: nuklear.h:3524
float rounding
Definition: nuklear.h:3579
float at_y
Definition: nuklear.h:3767
Definition: nuklear.h:2827
struct nk_style_text text
Definition: nuklear.h:3657
struct nk_vec2i b
Definition: nuklear.h:2912
nk_handle userdata
Definition: nuklear.h:3351
struct nk_color text_pressed_active
Definition: nuklear.h:3340
struct nk_color label_normal
Definition: nuklear.h:3540
Definition: nuklear.h:3589
struct nk_color combo_border_color
Definition: nuklear.h:3621
NK_API void nk_textedit_text(struct nk_text_edit *, const char *, int total_len)
NK_API void nk_str_delete_chars(struct nk_str *, int pos, int len)
struct nk_popup_buffer buf
Definition: nuklear.h:3809
Definition: nuklear.h:2836
struct nk_color color
Definition: nuklear.h:3251
nk_hash name
Definition: nuklear.h:3810
struct nk_allocator alloc
Definition: nuklear.h:3995
NK_API int nk_str_append_text_runes(struct nk_str *, const nk_rune *, int)
#define NK_INT8
Definition: nuklear.h:337
nk_command_custom_callback callback
Definition: nuklear.h:2987
Definition: nuklear.h:668
std::mutex m
Definition: faio.cpp:21
NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color)
Definition: nuklear.h:2547
NK_INT8 nk_char
Definition: nuklear.h:394
NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color)
Definition: nuklear.h:1882
struct nk_table * tables
Definition: nuklear.h:3862
struct nk_vec2 scrollbar_size
Definition: nuklear.h:3638
NK_API int nk_strtoi(const char *str, const char **endptr)
float max
Definition: nuklear.h:3709
struct nk_vec2 prev
Definition: nuklear.h:3052
enum nk_symbol_type sym_normal
Definition: nuklear.h:3551
Definition: nuklear.h:1881
Definition: nuklear.h:2722
struct nk_table * next
Definition: nuklear.h:3973
struct nk_style_item cursor_hover
Definition: nuklear.h:3404
struct nk_key keys[NK_KEY_MAX]
Definition: nuklear.h:3065
Definition: nuklear.h:3969
NK_API struct nk_style_item nk_style_item_hide(void)
NK_API int nk_combo_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
unsigned short line_thickness
Definition: nuklear.h:2952
NK_API void nk_label(struct nk_context *, const char *, nk_flags align)
nk_byte g
Definition: nuklear.h:453
Definition: nuklear.h:1715
NK_API int nk_style_set_cursor(struct nk_context *, enum nk_style_cursor)
Definition: nuklear.h:3715
int count
Definition: nuklear.h:1680
struct nk_color text_hover
Definition: nuklear.h:3274
NK_API const struct nk_command * nk__next(struct nk_context *, const struct nk_command *)
nk_tree_type
Definition: nuklear.h:476
NK_API int nk_stricmp(const char *s1, const char *s2)
Definition: nuklear.h:3488
NK_API int nk_str_insert_at_rune(struct nk_str *, int pos, const char *, int)
NK_API void nk_plot(struct nk_context *, enum nk_chart_type, const float *values, int count, int offset)
unsigned curve_segment_count
Definition: nuklear.h:987
nk_panel_type
Definition: nuklear.h:3690
short undo_point
Definition: nuklear.h:2708
int cursor
Definition: nuklear.h:2731
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3391
float delta_time_seconds
Definition: nuklear.h:4014
NK_API void nk_contextual_end(struct nk_context *)
NK_API int nk_combo_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
struct nk_command_buffer overlay
Definition: nuklear.h:4031
struct nk_command header
Definition: nuklear.h:2874
NK_API int nk_progress(struct nk_context *, nk_size *cur, nk_size max, int modifyable)
float rounding
Definition: nuklear.h:3409
short y
Definition: nuklear.h:2974
nk_size needed
Definition: nuklear.h:2542
struct nk_style_item normal
Definition: nuklear.h:3534
struct nk_vec2i begin
Definition: nuklear.h:2859
Definition: nuklear.h:1744
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3352
struct nk_buffer buffer
Definition: nuklear.h:2610
float x
Definition: nuklear.h:3757
struct nk_vec2i a
Definition: nuklear.h:2903
struct nk_style_item active
Definition: nuklear.h:3399
struct nk_style_edit edit
Definition: nuklear.h:3667
NK_API int nk_window_is_any_hovered(struct nk_context *)
Definition: nuklear.h:473
Definition: nuklear.h:3049
NK_API struct nk_vec2 nk_vec2iv(const int *xy)
unsigned short h
Definition: nuklear.h:2853
short cy
Definition: nuklear.h:2934
Definition: nuklear.h:969
unsigned char cursor_at_end_of_line
Definition: nuklear.h:2735
float border
Definition: nuklear.h:3628
NK_API int nk_combo_begin_text(struct nk_context *, const char *selected, int, struct nk_vec2 size)
#define NK_BUTTON_BEHAVIOR_STACK_SIZE
Definition: nuklear.h:3898
struct nk_style_button dec_button
Definition: nuklear.h:3385
NK_API void nk_input_glyph(struct nk_context *, const nk_glyph)
struct nk_style_item pressed_active
Definition: nuklear.h:3330
Definition: nuklear.h:475
nk_button_behavior
Definition: nuklear.h:466
NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context *, struct nk_vec2)
struct nk_vec2 label_padding
Definition: nuklear.h:3610
NK_API int nk_style_pop_float(struct nk_context *)
short y
Definition: nuklear.h:2984
float rounding
Definition: nuklear.h:3506
NK_API struct nk_rect nk_layout_space_bounds(struct nk_context *)
struct nk_table * prev
Definition: nuklear.h:3973
NK_API int nk_button_image_text_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, int, nk_flags alignment)
NK_API int nk_init_custom(struct nk_context *, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *)
struct nk_vec2i points[1]
Definition: nuklear.h:2954
Definition: nuklear.h:661
struct nk_style_tab tab
Definition: nuklear.h:3671
struct nk_color border_color
Definition: nuklear.h:3296
NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect *, struct nk_context *, struct nk_vec2)
NK_API double nk_strtod(const char *str, const char **endptr)
struct nk_window win
Definition: nuklear.h:3979
NK_API void nk_window_close(struct nk_context *ctx, const char *name)
struct nk_clipboard clip
Definition: nuklear.h:2726
nk_style_cursor
Definition: nuklear.h:2048
struct nk_window * begin
Definition: nuklear.h:4037
NK_API void nk_style_default(struct nk_context *)
NK_API void nk_input_scroll(struct nk_context *, struct nk_vec2 val)
NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect, int down)
#define NK_FLOAT_STACK_SIZE
Definition: nuklear.h:3910
Definition: nuklear.h:1719
struct nk_style_item cursor_hover
Definition: nuklear.h:3430
Definition: nuklear.h:3395
Definition: nuklear.h:2838
Definition: nuklear.h:3700
float y
Definition: nuklear.h:3717
Definition: nuklear.h:3701
int active
Definition: nuklear.h:3832
Definition: nuklear.h:665
NK_API void nk_free(struct nk_context *)
struct nk_color text_normal
Definition: nuklear.h:3469
unsigned short point_count
Definition: nuklear.h:2968
Definition: nuklear.h:496
int buffer_size
Definition: versiongenerate.py:65
Definition: nuklear.h:971
NK_API char * nk_str_at_char(struct nk_str *, int pos)
Definition: nuklear.h:699
Definition: nuklear.h:697
NK_API int nk_button_label_styled(struct nk_context *, const struct nk_style_button *, const char *title)
NK_API struct nk_color nk_rgb(int r, int g, int b)
NK_API int nk_tree_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
Definition: nuklear.h:474
enum nk_symbol_type sym_active
Definition: nuklear.h:3553
Definition: nuklear.h:500
NK_API void nk_combobox_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size)
unsigned int has_scrolling
Definition: nuklear.h:3771
int len
Definition: nuklear.h:2611
unsigned int type
Definition: nuklear.h:2539
NK_API void nk_tree_state_pop(struct nk_context *)
NK_API int nk_combo_begin_label(struct nk_context *, const char *selected, struct nk_vec2 size)
NK_API int nk_stricmpn(const char *s1, const char *s2, int n)
Definition: nuklear.h:672
#define NK_UINT32
Definition: nuklear.h:359
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3450
Definition: nuklear.h:3806
NK_API int nk_style_push_flags(struct nk_context *, nk_flags *, nk_flags)
int select_start
Definition: nuklear.h:3836
int index
Definition: nuklear.h:3712
struct nk_style_item active
Definition: nuklear.h:3536
NK_API void nk_window_collapse_if(struct nk_context *, const char *name, enum nk_collapse_states, int cond)
Definition: nuklear.h:1889
struct nk_vec2 button_padding
Definition: nuklear.h:3559
Definition: nuklear.h:1742
float contextual_border
Definition: nuklear.h:3630
Definition: nuklear.h:2040
Definition: nuklear.h:1181
char text[NK_INPUT_MAX]
Definition: nuklear.h:3066
nk_uint y
Definition: nuklear.h:463
void(* nk_plugin_copy)(nk_handle, const char *, int len)
Definition: nuklear.h:482
unsigned char active
Definition: nuklear.h:2739
float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]
Definition: nuklear.h:3745
NK_API void nk_buffer_push(struct nk_buffer *, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align)
NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx)
NK_API void nk_color_fv(float *rgba_out, struct nk_color)
int state
Definition: nuklear.h:3841
NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input *, struct nk_rect)
Definition: nuklear.h:2716
Definition: nuklear.h:3454
nk_keys
Definition: nuklear.h:660
unsigned arc_segment_count
Definition: nuklear.h:986
#define NK_INT16
Definition: nuklear.h:343
struct nk_command header
Definition: nuklear.h:2973
Definition: nuklear.h:2830
Definition: nuklear.h:3586
NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
nk_size end
Definition: nuklear.h:3012
nk_style_item_type
Definition: nuklear.h:3244
const struct nk_cursor * cursor_active
Definition: nuklear.h:3653
Definition: nuklear.h:2557
unsigned circle_segment_count
Definition: nuklear.h:985
enum nk_symbol_type dec_symbol
Definition: nuklear.h:3387
int prev
Definition: nuklear.h:3822
struct nk_command header
Definition: nuklear.h:2901
Definition: nuklear.h:2609
struct nk_command header
Definition: nuklear.h:2851
Definition: nuklear.h:2034
Definition: nuklear.h:1883
struct nk_color label_hover
Definition: nuklear.h:3604
enum nk_symbol_type maximize_symbol
Definition: nuklear.h:3600
Definition: nuklear.h:467
Definition: nuklear.h:3794
struct nk_vec2i b
Definition: nuklear.h:2904
struct nk_style_button button
Definition: nuklear.h:3658
Definition: nuklear.h:1177
struct nk_style_scrollbar scrollh
Definition: nuklear.h:3669
Definition: nuklear.h:1718
NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
NK_API void nk_group_scrolled_end(struct nk_context *)
nk_handle userdata
Definition: nuklear.h:3449
unsigned active_con
Definition: nuklear.h:3814
const float * ratio
Definition: nuklear.h:3738
NK_API int nk_contextual_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
unsigned char single_line
Definition: nuklear.h:2738
Definition: nuklear.h:1893
Definition: nuklear.h:1178
struct nk_color foreground
Definition: nuklear.h:2994
struct nk_vec2 padding
Definition: nuklear.h:3641
Definition: nuklear.h:3756
Definition: nuklear.h:2026
struct nk_table tbl
Definition: nuklear.h:3977
struct nk_panel * parent
Definition: nuklear.h:3777
struct nk_style_item normal
Definition: nuklear.h:3490
struct nk_vec2 scrollbar
Definition: nuklear.h:2729
NK_API struct nk_vec2 nk_vec2(float x, float y)
unsigned char padding1
Definition: nuklear.h:2740
NK_API void nk_menubar_end(struct nk_context *)
struct nk_vec2 scrollbar_size
Definition: nuklear.h:3483
struct nk_color border_color
Definition: nuklear.h:3269
NK_API void nk_buffer_mark(struct nk_buffer *, enum nk_buffer_allocation_type type)
#define NK_WINDOW_MAX_NAME
Definition: nuklear.h:3784
Definition: nuklear.h:676
nk_uint * offset_x
Definition: nuklear.h:3765
int begin
Definition: nuklear.h:1680
typedef void(ENET_CALLBACK *ENetPacketFreeCallback)(struct _ENetPacket *)
struct nk_config_stack_user_font fonts
Definition: nuklear.h:3959
union nk_page_data data
Definition: nuklear.h:3983
Definition: nuklear.h:1886
NK_API int nk_combo_begin_symbol(struct nk_context *, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_image(struct nk_context *, struct nk_image)
float footer_height
Definition: nuklear.h:3768
Definition: nuklear.h:2037
#define NK_VECTOR_STACK_SIZE
Definition: nuklear.h:3914
Definition: nuklear.h:2842
Definition: nuklear.h:3004
struct nk_draw_null_texture null
Definition: nuklear.h:988
NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
Definition: nuklear.h:3249
NK_API int nk_strlen(const char *str)
struct nk_style_item normal
Definition: nuklear.h:3456
float height
Definition: nuklear.h:2365
unsigned short rounding
Definition: nuklear.h:2884
Definition: nuklear.h:692
struct nk_page * next
Definition: nuklear.h:3990
NK_API float nk_strtof(const char *str, const char **endptr)
NK_UINT32 nk_uint
Definition: nuklear.h:400
struct nk_vec2 spacing
Definition: nuklear.h:3560
#define NK_SIZE_TYPE
Definition: nuklear.h:374
struct nk_color bar_active
Definition: nuklear.h:3366
Definition: nuklear.h:2823
Definition: nuklear.h:3614
struct nk_color cursor_text_normal
Definition: nuklear.h:3465
NK_API struct nk_color nk_rgb_fv(const float *rgb)
NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name)
int tree_depth
Definition: nuklear.h:3744
NK_API void nk_layout_row_template_begin(struct nk_context *, float height)
NK_API void nk_draw_text(struct nk_command_buffer *, struct nk_rect, const char *text, int len, const struct nk_user_font *, struct nk_color, struct nk_color)
float b
Definition: nuklear.h:454
enum nk_allocation_type type
Definition: nuklear.h:3996
struct nk_command header
Definition: nuklear.h:2965
unsigned int seq
Definition: nuklear.h:3845
struct nk_buffer memory
Definition: nuklear.h:4009
nk_text_align
Definition: nuklear.h:1741
NK_API struct nk_color nk_hsva_iv(const int *hsva)
NK_API void nk_combobox(struct nk_context *, const char **items, int count, int *selected, int item_height, struct nk_vec2 size)
struct nk_scroll scrollbar
Definition: nuklear.h:3826
NK_API void nk_buffer_reset(struct nk_buffer *, enum nk_buffer_allocation_type type)
NK_API int nk_str_insert_text_runes(struct nk_str *, int pos, const nk_rune *, int)
enum nk_symbol_type sym_maximize
Definition: nuklear.h:3575
NK_API void nk_textedit_delete_selection(struct nk_text_edit *)
int active
Definition: nuklear.h:3753
struct nk_window * end
Definition: nuklear.h:4038
Definition: nuklear.h:680
Definition: nuklear.h:2032
struct nk_rect item
Definition: nuklear.h:3743
NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color)
NK_API int nk_group_scrolled_offset_begin(struct nk_context *, nk_uint *x_offset, nk_uint *y_offset, const char *, nk_flags)
float item_offset
Definition: nuklear.h:3741
Definition: nuklear.h:461
struct nk_color text
Definition: nuklear.h:3567
NK_API struct nk_color nk_rgba(int r, int g, int b, int a)
Definition: nuklear.h:2554
NK_API void * nk_buffer_memory(struct nk_buffer *)
nk_text_edit_type
Definition: nuklear.h:2714
NK_API void nk_textedit_init_fixed(struct nk_text_edit *, void *memory, nk_size size)
NK_API int nk_init_fixed(struct nk_context *, void *memory, nk_size size, const struct nk_user_font *)
unsigned short h
Definition: nuklear.h:2886
#define NK_SATURATE(x)
Definition: nuklear.h:4054
struct nk_style_slider slider
Definition: nuklear.h:3664
struct nk_color label_active
Definition: nuklear.h:3498
Definition: nuklear.h:2023
Definition: nuklear.h:3729
NK_API void nk_stroke_curve(struct nk_command_buffer *, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color)
float popup_border
Definition: nuklear.h:3634
NK_API int nk_button_image(struct nk_context *, struct nk_image img)
NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region)
nk_hash name
Definition: nuklear.h:3819
float border
Definition: nuklear.h:3556
nk_size parent
Definition: nuklear.h:3750
NK_API int nk_combo(struct nk_context *, const char **items, int count, int selected, int item_height, struct nk_vec2 size)
Definition: nuklear.h:3844
Definition: nuklear.h:2044
Definition: nuklear.h:1182
nk_byte a
Definition: nuklear.h:453
NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a)
NK_API void nk_str_clear(struct nk_str *)
float rounding
Definition: nuklear.h:3528
float a[2]
Definition: nuklear.h:2945
#define NK_TEXTEDIT_UNDOCHARCOUNT
Definition: nuklear.h:2688
NK_API const void * nk_buffer_memory_const(const struct nk_buffer *)
#define nk_ptr_add_const(t, p, i)
Definition: nuklear.h:4071
Definition: nuklear.h:2837
NK_API void nk_buffer_init_fixed(struct nk_buffer *, void *memory, nk_size size)
float x
Definition: nuklear.h:457
Definition: nuklear.h:977
Definition: nuklear.h:2021
NK_API void nk_popup_close(struct nk_context *)
NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color)
Definition: nuklear.h:2033
enum nk_symbol_type inc_symbol
Definition: nuklear.h:3445
short x
Definition: nuklear.h:2995
nk_uint nk_rune
Definition: nuklear.h:406
struct nk_color text_active
Definition: nuklear.h:3275
struct nk_page_element * freelist
Definition: nuklear.h:3999
struct nk_window * next
Definition: nuklear.h:3867
NK_API struct nk_color nk_color_picker(struct nk_context *, struct nk_color, enum nk_color_format)
struct nk_vec2 combo_padding
Definition: nuklear.h:3644
NK_API int nk_str_append_text_utf8(struct nk_str *, const char *, int)
struct nk_color text_hover
Definition: nuklear.h:3304
NK_API void nk_text_colored(struct nk_context *, const char *, int, nk_flags, struct nk_color)
int end
Definition: nuklear.h:1680
struct nk_config_stack_flags flags
Definition: nuklear.h:3957
nk_panel_set
Definition: nuklear.h:3699
unsigned short w
Definition: nuklear.h:2996
float x
Definition: nuklear.h:3717
struct nk_image image
Definition: nuklear.h:3250
float cursor_rounding
Definition: nuklear.h:3412
NK_API int nk_checkbox_flags_text(struct nk_context *, const char *, int, unsigned int *flags, unsigned int value)
Definition: nuklear.h:3976
NK_API int nk_button_image_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img)
unsigned short line_thickness
Definition: nuklear.h:2866
int total_height
Definition: nuklear.h:1682
NK_API struct nk_rect nk_rect(float x, float y, float w, float h)
struct nk_vec2 touch_padding
Definition: nuklear.h:3283
Definition: nuklear.h:3798
nk_orientation
Definition: nuklear.h:468
NK_API void nk_style_show_cursor(struct nk_context *)
struct nk_color text_background
Definition: nuklear.h:3341
struct nk_window * prev
Definition: nuklear.h:3868
int cursor
Definition: nuklear.h:3823
struct nk_vec2 min_size
Definition: nuklear.h:3639
struct nk_command header
Definition: nuklear.h:2933
struct nk_color color
Definition: nuklear.h:2929
float spacing
Definition: nuklear.h:3312
struct nk_style_item normal
Definition: nuklear.h:3591
Definition: nuklear.h:2824
struct nk_vec2 padding
Definition: nuklear.h:3609
nk_widget_layout_states
Definition: nuklear.h:1709
Definition: nuklear.h:2831
struct nk_style_scrollbar scrollv
Definition: nuklear.h:3670
NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value)
Definition: nuklear.h:3421
enum nk_anti_aliasing line_AA
Definition: nuklear.h:983
struct nk_style_item active
Definition: nuklear.h:3268
nk_collapse_states
Definition: nuklear.h:469
short redo_point
Definition: nuklear.h:2709
NK_API const char * nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len)
Definition: nuklear.h:499
Definition: nuklear.h:456
NK_API int nk_chart_begin_colored(struct nk_context *, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max)
NK_API void nk_style_hide_cursor(struct nk_context *)
NK_API int nk_menu_begin_image_text(struct nk_context *, const char *, int, nk_flags align, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:3725
struct nk_color border_color
Definition: nuklear.h:3361
Definition: nuklear.h:1712
Definition: nuklear.h:2025
NK_API int nk_group_scrolled_begin(struct nk_context *, struct nk_scroll *, const char *title, nk_flags)
struct nk_color color
Definition: nuklear.h:2887
NK_API void nk_str_remove_runes(struct nk_str *str, int len)
struct nk_vec2 spacing
Definition: nuklear.h:3637
float item_width
Definition: nuklear.h:3739
Definition: nuklear.h:2826
Definition: nuklear.h:2050
Definition: nuklear.h:3356
#define NK_ALIGN_PTR(x, mask)
Definition: nuklear.h:4092
struct nk_color color
Definition: nuklear.h:2906
int cursor_visible
Definition: nuklear.h:3655
NK_API int nk_widget_has_mouse_click_down(struct nk_context *, enum nk_buttons, int down)
#define NK_CLAMP(i, v, x)
Definition: nuklear.h:317
struct nk_style_combo combo
Definition: nuklear.h:3672
struct nk_style_property property
Definition: nuklear.h:3666
unsigned short region[4]
Definition: nuklear.h:461
NK_API void nk_input_begin(struct nk_context *)
int length
Definition: nuklear.h:3834
struct nk_window * win
Definition: nuklear.h:3807
struct nk_color contextual_border_color
Definition: nuklear.h:3622
Definition: nuklear.h:2909
NK_API int nk_option_text(struct nk_context *, const char *, int, int active)
void * ptr
Definition: nuklear.h:460
struct nk_menu_state menu
Definition: nuklear.h:3773
NK_API void nk_stroke_rect(struct nk_command_buffer *, struct nk_rect, float rounding, float line_thickness, struct nk_color)
NK_API int nk_menu_begin_symbol_text(struct nk_context *, const char *, int, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_push_scissor(struct nk_command_buffer *, struct nk_rect)
NK_API const struct nk_command * nk__begin(struct nk_context *)
NK_API nk_flags nk_chart_push_slot(struct nk_context *, float, int)
Definition: nuklear.h:2028
nk_edit_flags
Definition: nuklear.h:1877
#define NK_INBOX(px, py, x, y, w, h)
Definition: nuklear.h:4058
int value
Definition: der_length_ia5_string.c:21
#define nk_vec2_sub(a, b)
Definition: nuklear.h:4065
Definition: nuklear.h:470
NK_API int nk_str_append_str_char(struct nk_str *, const char *)
float indent
Definition: nuklear.h:3580
Definition: nuklear.h:700
struct nk_color selected_color
Definition: nuklear.h:3523
unsigned char initialized
Definition: nuklear.h:2736
Definition: nuklear.h:2029
Definition: nuklear.h:1180
NK_API int nk_input_is_key_down(const struct nk_input *, enum nk_keys)
Definition: nuklear.h:501
NK_API int nk_window_is_hovered(struct nk_context *)
short x
Definition: nuklear.h:2974
NK_API double nk_propertyd(struct nk_context *, const char *name, double min, double val, double max, double step, float inc_per_pixel)
#define NK_PI
Definition: nuklear.h:4049
struct nk_cursor * cursor_last
Definition: nuklear.h:3654
nk_size last
Definition: nuklear.h:3012
NK_API int nk_filter_decimal(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:1899
Definition: nuklear.h:469
float height
Definition: nuklear.h:2997
NK_API int nk_filter_binary(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_init(struct nk_context *, struct nk_allocator *, const struct nk_user_font *)
Definition: nuklear.h:2030
NK_API int nk_radio_label(struct nk_context *, const char *, int *active)
struct nk_vec2 spacing
Definition: nuklear.h:3611
NK_API void nk_contextual_close(struct nk_context *)
short y
Definition: nuklear.h:2919
NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
void(* nk_command_custom_callback)(void *canvas, short x, short y, unsigned short w, unsigned short h, nk_handle callback_data)
Definition: nuklear.h:2980
NK_API void nk_textedit_init(struct nk_text_edit *, struct nk_allocator *, nk_size size)
const struct nk_cursor * cursors[NK_CURSOR_COUNT]
Definition: nuklear.h:3652
struct nk_vec2 spacing
Definition: nuklear.h:3379
const struct nk_draw_vertex_layout_element * vertex_layout
Definition: nuklear.h:989
struct nk_style_chart chart
Definition: nuklear.h:3668
#define NK_UTF_SIZE
Definition: nuklear.h:255
struct nk_vec2 popup_padding
Definition: nuklear.h:3643
NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols)
short delete_length
Definition: nuklear.h:2701
NK_API void nk_fill_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, struct nk_color)
NK_API const char * nk_str_get_const(const struct nk_str *)
NK_API int nk_textedit_cut(struct nk_text_edit *)
Definition: nuklear.h:972
NK_API void nk_property_double(struct nk_context *, const char *name, double min, double *val, double max, double step, float inc_per_pixel)
Definition: nuklear.h:3563
struct nk_color cursor_text_hover
Definition: nuklear.h:3466
NK_API int nk_button_image_label_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_combo_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size)
NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color)
float border
Definition: nuklear.h:3435
float rounding
Definition: nuklear.h:3376
NK_API void nk_stroke_polyline(struct nk_command_buffer *, float *points, int point_count, float line_thickness, struct nk_color col)
NK_API void nk_text_wrap_colored(struct nk_context *, const char *, int, struct nk_color)
NK_API enum nk_widget_layout_states nk_widget(struct nk_rect *, const struct nk_context *)
nk_edit_events
Definition: nuklear.h:1898
NK_API struct nk_vec2 nk_rect_pos(struct nk_rect)
Definition: nuklear.h:3724
struct nk_text_undo_state undo
Definition: nuklear.h:2742
NK_API int nk_input_is_mouse_released(const struct nk_input *, enum nk_buttons)
Definition: nuklear.h:2038
NK_API void nk_property_int(struct nk_context *, const char *name, int min, int *val, int max, int step, float inc_per_pixel)
struct nk_style_button button
Definition: nuklear.h:3550
#define NK_SCROLLBAR_HIDING_TIMEOUT
Definition: nuklear.h:263
enum nk_symbol_type sym_right
Definition: nuklear.h:3502
Definition: nuklear.h:3650
NK_API void nk_color_hex_rgba(char *output, struct nk_color)
#define NK_MIN(a, b)
Definition: nuklear.h:315
Definition: nuklear.h:3792
struct nk_vec2 group_padding
Definition: nuklear.h:3642
Definition: nuklear.h:468
nk_handle userdata
Definition: nuklear.h:485
NK_API void nk_style_load_cursor(struct nk_context *, enum nk_style_cursor, const struct nk_cursor *)
unsigned int size
Definition: nuklear.h:3989
Definition: nuklear.h:455
Definition: nuklear.h:457
NK_API int nk_input_is_mouse_pressed(const struct nk_input *, enum nk_buttons)
Definition: nuklear.h:2039
struct nk_style_item cursor_normal
Definition: nuklear.h:3370
#define NK_VALUE_PAGE_CAPACITY
Definition: nuklear.h:3966
Definition: nuklear.h:474
NK_API void nk_push_custom(struct nk_command_buffer *, struct nk_rect, nk_command_custom_callback, nk_handle usr)
Definition: nuklear.h:2957
Definition: nuklear.h:490
enum nk_style_header_align align
Definition: nuklear.h:3608
NK_API int nk_str_len_char(struct nk_str *)
int active
Definition: nuklear.h:2558
Definition: nuklear.h:2053
unsigned int clicked
Definition: nuklear.h:3062
NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input *, struct nk_rect)
void * ptr
Definition: nuklear.h:2562
Definition: nuklear.h:2024
NK_API const char * nk_style_get_color_by_name(enum nk_style_colors)
void(* nk_query_font_glyph_f)(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
Definition: nuklear.h:2345
Definition: nuklear.h:3728
NK_API void nk_stroke_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color)
Definition: nuklear.h:975
Definition: nuklear.h:2705
Definition: nuklear.h:662
nk_size vertex_alignment
Definition: nuklear.h:991
NK_API void nk_tooltip_end(struct nk_context *)
Definition: nuklear.h:679
Definition: nuklear.h:502
struct nk_color border_color
Definition: nuklear.h:3522
struct nk_style_item cursor_normal
Definition: nuklear.h:3403
unsigned short h
Definition: nuklear.h:2921
Definition: nuklear.h:1901
Definition: nuklear.h:503
short w
Definition: nuklear.h:458
NK_API void nk_spacing(struct nk_context *, int cols)
Definition: nuklear.h:467
Definition: nuklear.h:2537
Definition: nuklear.h:682
struct nk_color text_background
Definition: nuklear.h:3272
float y
Definition: nuklear.h:455
NK_API struct nk_color nk_rgba_hex(const char *rgb)
struct nk_vec2i points[1]
Definition: nuklear.h:2961
struct nk_vec2 padding
Definition: nuklear.h:3581
struct nk_command header
Definition: nuklear.h:2958
struct nk_style_item active
Definition: nuklear.h:3492
GLuint texture
Definition: sdl2backend.cpp:527
NK_API int nk_button_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags text_alignment)
#define NK_STATIC_ASSERT(exp)
Definition: nuklear.h:304
NK_API struct nk_image nk_subimage_ptr(void *, unsigned short w, unsigned short h, struct nk_rect sub_region)
NK_API void nk_text_wrap(struct nk_context *, const char *, int)
NK_API struct nk_image nk_image_handle(nk_handle)
NK_API struct nk_image nk_image_ptr(void *)
short y
Definition: nuklear.h:2927
NK_API float nk_window_get_width(const struct nk_context *)
NK_API int nk_image_is_subimage(const struct nk_image *img)
nk_size begin
Definition: nuklear.h:3012
struct nk_command header
Definition: nuklear.h:2883
Definition: nuklear.h:973
Definition: nuklear.h:1179
NK_API int nk_style_push_font(struct nk_context *, struct nk_user_font *)
struct nk_context * ctx
Definition: nuklear.h:1683
unsigned char mode
Definition: nuklear.h:2734
struct nk_style_item hover
Definition: nuklear.h:3359
unsigned short h
Definition: nuklear.h:2996
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
struct nk_color text_hover_active
Definition: nuklear.h:3339
NK_API int nk_selectable_label(struct nk_context *, const char *, nk_flags align, int *value)
struct nk_style_button tab_minimize_button
Definition: nuklear.h:3571
struct nk_vec2 padding
Definition: nuklear.h:3484
NK_API struct nk_color nk_hsva(int h, int s, int v, int a)
struct nk_vec2 spacing
Definition: nuklear.h:3582
#define NK_STYLE_ITEM_STACK_SIZE
Definition: nuklear.h:3906
Definition: nuklear.h:669
NK_API int nk_str_insert_text_utf8(struct nk_str *, int pos, const char *, int)
Definition: nuklear.h:3264
NK_API void nk_tooltip(struct nk_context *, const char *)
Definition: nuklear.h:2563
struct nk_color text_active
Definition: nuklear.h:3305
#define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
Definition: nuklear.h:3684
nk_plugin_alloc alloc
Definition: nuklear.h:486
NK_API void nk_combo_close(struct nk_context *)
struct nk_color text_hover
Definition: nuklear.h:3470
NK_API int nk_radio_text(struct nk_context *, const char *, int, int *active)
NK_API void nk_buffer_clear(struct nk_buffer *)
Definition: nuklear.h:3761
nk_uint scroll_value
Definition: nuklear.h:1685
short undo_char_point
Definition: nuklear.h:2710
enum nk_symbol_type sym_hover
Definition: nuklear.h:3552
enum nk_symbol_type close_symbol
Definition: nuklear.h:3598
int id
Definition: nuklear.h:460
Definition: nuklear.h:2362
NK_API struct nk_vec2 nk_window_get_size(const struct nk_context *)
Definition: nuklear.h:465
nk_uint * offset_y
Definition: nuklear.h:3766
struct nk_command header
Definition: nuklear.h:2950
struct nk_color label_hover
Definition: nuklear.h:3497
Definition: nuklear.h:1717
nk_size end
Definition: nuklear.h:3752
int select_end
Definition: nuklear.h:2733
NK_API const char * nk_str_at_char_const(const struct nk_str *, int pos)
struct nk_configuration_stacks stacks
Definition: nuklear.h:4013
struct nk_style_item cursor_active
Definition: nuklear.h:3431
Definition: nuklear.h:1900
Definition: nuklear.h:2900
NK_API nk_handle nk_handle_id(int)
NK_API int nk_combo_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
unsigned short h
Definition: nuklear.h:2893
NK_UINT8 nk_uchar
Definition: nuklear.h:395
int active
Definition: nuklear.h:3822
NK_API struct nk_color nk_rgb_f(float r, float g, float b)
Definition: nuklear.h:2721
enum nk_allocation_type type
Definition: nuklear.h:2568
float r
Definition: nuklear.h:454
nk_window_flags
Definition: nuklear.h:3788
short x
Definition: nuklear.h:2892
nk_chart_type
Definition: nuklear.h:471
float x
Definition: nuklear.h:455
struct nk_color symbol_hover
Definition: nuklear.h:3546
struct nk_mouse mouse
Definition: nuklear.h:3072
enum nk_chart_type type
Definition: nuklear.h:3706
Definition: nuklear.h:498
struct nk_rect bounds
Definition: nuklear.h:3764
Definition: nuklear.h:2018
Definition: nuklear.h:2548
NK_API int nk_contextual_item_label(struct nk_context *, const char *, nk_flags align)
#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)
Definition: nuklear.h:3925
struct nk_color border_color
Definition: nuklear.h:3426
NK_API int nk_list_view_begin(struct nk_context *, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count)
float rounding
Definition: nuklear.h:3481
nk_size size
Definition: nuklear.h:4001
struct nk_vec2 padding
Definition: nuklear.h:3346
NK_API void nk_stroke_polygon(struct nk_command_buffer *, float *, int point_count, float line_thickness, struct nk_color)
unsigned combo_count
Definition: nuklear.h:3812
NK_API void nk_popup_end(struct nk_context *)
int build
Definition: nuklear.h:4034
struct nk_page * pages
Definition: nuklear.h:3998
NK_API void nk_input_motion(struct nk_context *, int x, int y)
NK_API int nk_textedit_paste(struct nk_text_edit *, char const *, int len)
Definition: nuklear.h:3321
NK_API int nk_color_pick(struct nk_context *, struct nk_color *, enum nk_color_format)
Definition: nuklear.h:2829
NK_API int nk_utf_len(const char *, int byte_len)
float g
Definition: nuklear.h:454
Definition: nuklear.h:974
NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading)
Definition: nuklear.h:1716
nk_size vertex_size
Definition: nuklear.h:990
unsigned short w
Definition: nuklear.h:2921
Definition: nuklear.h:1720
NK_API struct nk_color nk_hsva_fv(const float *hsva)
Definition: nuklear.h:462
Definition: nuklear.h:696
nk_size cap
Definition: nuklear.h:4002
Definition: nuklear.h:1884
Definition: nuklear.h:1176
enum nk_symbol_type inc_symbol
Definition: nuklear.h:3386
NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color)
Definition: nuklear.h:3988
struct nk_keyboard keyboard
Definition: nuklear.h:3071
unsigned short rounding
Definition: nuklear.h:2875
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3353
#define NK_UINT16
Definition: nuklear.h:346
Definition: nuklear.h:475
unsigned short w
Definition: nuklear.h:461
Definition: nuklear.h:2925
unsigned short w
Definition: nuklear.h:2928
#define NK_TEXTEDIT_UNDOSTATECOUNT
Definition: nuklear.h:2684
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3516
NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value)
struct nk_style_scrollbar scrollbar
Definition: nuklear.h:3460
struct nk_color bar_normal
Definition: nuklear.h:3364
nk_flags last_widget_state
Definition: nuklear.h:4011
Definition: nuklear.h:3802
#define nk_foreach(c, ctx)
Definition: nuklear.h:1011
struct nk_color color
Definition: nuklear.h:3707
struct nk_command header
Definition: nuklear.h:2926
int(* nk_plugin_filter)(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:480
struct nk_style_item normal_active
Definition: nuklear.h:3328
Definition: nuklear.h:476
NK_API float nk_window_get_height(const struct nk_context *)
NK_API float nk_widget_height(struct nk_context *)
NK_API int nk_menu_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
NK_API int nk_slide_int(struct nk_context *, int min, int val, int max, int step)
Definition: nuklear.h:3733
NK_API int nk_filter_oct(const struct nk_text_edit *, nk_rune unicode)
float filled
Definition: nuklear.h:3742
#define NK_LEN(a)
Definition: nuklear.h:4055
NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
Definition: nuklear.h:2828
Definition: nuklear.h:2990
Definition: nuklear.h:693
NK_API int nk_slider_float(struct nk_context *, float min, float *val, float max, float step)
NK_API int nk_window_is_hidden(struct nk_context *, const char *)
NK_API void nk_fill_triangle(struct nk_command_buffer *, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color)
Definition: nuklear.h:1880
short cx
Definition: nuklear.h:2934
#define NK_INTERN
Definition: nuklear.h:286
struct nk_command_buffer buffer
Definition: nuklear.h:3852
NK_API int nk_slider_int(struct nk_context *, int min, int *val, int max, int step)
nk_size allocated
Definition: nuklear.h:2541
nk_hash name
Definition: nuklear.h:3838
Definition: nuklear.h:468
struct nk_vec2i end
Definition: nuklear.h:2860
NK_API int nk_contextual_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
unsigned con_count
Definition: nuklear.h:3813
NK_API void nk_input_button(struct nk_context *, enum nk_buttons, int x, int y, int down)
NK_API int nk_item_is_any_active(struct nk_context *)
NK_API void nk_label_colored_wrap(struct nk_context *, const char *, struct nk_color)
struct nk_style_toggle checkbox
Definition: nuklear.h:3662
void(* draw_end)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:3288
NK_API void nk_input_key(struct nk_context *, enum nk_keys, int down)
NK_API struct nk_style_item nk_style_item_color(struct nk_color)
Definition: nuklear.h:2850
#define SEEK_SET
Definition: zconf.h:388
Definition: nuklear.h:677
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
NK_API int nk_button_push_behavior(struct nk_context *, enum nk_button_behavior)
unsigned short table_count
Definition: nuklear.h:3863
#define nk_ptr_add(t, p, i)
Definition: nuklear.h:4070
NK_API float nk_slide_float(struct nk_context *, float min, float val, float max, float step)
NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color)
Definition: nuklear.h:667
NK_API void nk_fill_polygon(struct nk_command_buffer *, float *, int point_count, struct nk_color)
nk_size size
Definition: nuklear.h:2562
short x
Definition: nuklear.h:2877
NK_API float nk_widget_width(struct nk_context *)
struct nk_color border_color
Definition: nuklear.h:3400
Definition: nuklear.h:1747
Definition: nuklear.h:3532
#define nk_vec2_add(a, b)
Definition: nuklear.h:4066
NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input *, struct nk_rect)
float cursor_border
Definition: nuklear.h:3411
NK_API int nk_chart_begin(struct nk_context *, enum nk_chart_type, int num, float min, float max)
NK_API int nk_style_pop_vec2(struct nk_context *)
Definition: nuklear.h:2054
struct nk_config_stack_style_item style_items
Definition: nuklear.h:3954
NK_API nk_size nk_buffer_total(struct nk_buffer *)
nk_size size
Definition: nuklear.h:2540
Definition: nuklear.h:681
NK_API nk_handle nk_handle_ptr(void *)
unsigned short h
Definition: nuklear.h:2985
unsigned int clicked
Definition: nuklear.h:3046
struct nk_style_item cursor_active
Definition: nuklear.h:3372
NK_API void nk_window_show(struct nk_context *, const char *name, enum nk_show_states)
struct nk_style style
Definition: nuklear.h:4008
Definition: nuklear.h:1752
NK_API void nk_tree_pop(struct nk_context *)
float range
Definition: nuklear.h:3709
const struct nk_user_font * font
Definition: nuklear.h:2992
Definition: gtest_output_test_.cc:544
NK_API void nk_textedit_undo(struct nk_text_edit *)
NK_API unsigned nk_check_flags_text(struct nk_context *, const char *, int, unsigned int flags, unsigned int value)
unsigned int count
Definition: nuklear.h:4042
struct nk_popup_state popup
Definition: nuklear.h:3858
NK_API float nk_layout_ratio_from_pixel(struct nk_context *, float pixel_width)
Definition: nuklear.h:1750
struct nk_vec2 padding
Definition: nuklear.h:3281
NK_API nk_flags nk_edit_buffer(struct nk_context *, nk_flags, struct nk_text_edit *, nk_plugin_filter)
float y
Definition: nuklear.h:457
int active
Definition: nuklear.h:3811
short x
Definition: nuklear.h:456
struct nk_color right
Definition: nuklear.h:2897
Definition: nuklear.h:3696
NK_API int nk_style_pop_style_item(struct nk_context *)
nk_handle userdata
Definition: nuklear.h:2363
Definition: nuklear.h:497
uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
Definition: adler32.c:60
struct nk_style_item hover
Definition: nuklear.h:3424
nk_plugin_filter filter
Definition: nuklear.h:2728
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3417
struct nk_style_item normal
Definition: nuklear.h:3423
NK_API int nk_checkbox_flags_label(struct nk_context *, const char *, unsigned int *flags, unsigned int value)
struct nk_color symbol_active
Definition: nuklear.h:3547
nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]
Definition: nuklear.h:2707
float scrollbar_hiding_timer
Definition: nuklear.h:3854
NK_API int nk_str_append_str_utf8(struct nk_str *, const char *)
nk_text_alignment
Definition: nuklear.h:1749
Definition: nuklear.h:2822
#define NK_API
Definition: nuklear.h:282
struct nk_rect bounds
Definition: nuklear.h:3850
Definition: nuklear.h:2715
unsigned short w
Definition: nuklear.h:2985
NK_API int nk_window_is_active(struct nk_context *, const char *)
Definition: nuklear.h:471
unsigned short line_thickness
Definition: nuklear.h:2920
Definition: nuklear.h:466
struct nk_style_window_header header
Definition: nuklear.h:3615
Definition: nuklear.h:3587
float global_alpha
Definition: nuklear.h:982
struct nk_command header
Definition: nuklear.h:2891
Definition: nuklear.h:2982
struct nk_color color
Definition: nuklear.h:2879
Definition: nuklear.h:470
unsigned capacity
Definition: nuklear.h:4000
NK_API int nk_style_push_color(struct nk_context *, struct nk_color *, struct nk_color)
struct nk_vec2 padding
Definition: nuklear.h:3529
Definition: nuklear.h:1887
NK_API void nk_style_load_all_cursors(struct nk_context *, struct nk_cursor *)
struct nk_vec2 touch_padding
Definition: nuklear.h:3347
struct nk_color color
Definition: nuklear.h:2951
struct nk_style_item fixed_background
Definition: nuklear.h:3616
Definition: nuklear.h:2020
nk_byte b
Definition: nuklear.h:453
NK_API int nk_input_has_mouse_click(const struct nk_input *, enum nk_buttons)
NK_API int nk_combo_begin_color(struct nk_context *, struct nk_color color, struct nk_vec2 size)
NK_API void nk_str_free(struct nk_str *)
int show_buttons
Definition: nuklear.h:3383
NK_API int nk_option_label(struct nk_context *, const char *, int active)
nk_size last
Definition: nuklear.h:3751
float border
Definition: nuklear.h:3410
nk_allocation_type
Definition: nuklear.h:2546
void(* nk_plugin_free)(nk_handle, void *old)
Definition: nuklear.h:479
struct nk_vec2i a
Definition: nuklear.h:2911
nk_plugin_paste paste
Definition: nuklear.h:2694
NK_API int nk_combo_begin_image_label(struct nk_context *, const char *selected, struct nk_image, struct nk_vec2 size)
struct nk_color cursor_border_color
Definition: nuklear.h:3432
nk_size next
Definition: nuklear.h:2844
struct nk_color color
Definition: nuklear.h:2959
struct nk_style_item background
Definition: nuklear.h:3565
Definition: nuklear.h:2035
NK_API void nk_textedit_free(struct nk_text_edit *)
struct nk_scroll scrollbar
Definition: nuklear.h:3851
NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color)
struct nk_buffer * base
Definition: nuklear.h:3008
float(* nk_text_width_f)(nk_handle, float h, const char *, int len)
Definition: nuklear.h:2344
int use_clipping
Definition: nuklear.h:3010
NK_API struct nk_command_buffer * nk_window_get_canvas(struct nk_context *)
NK_API int nk_checkbox_text(struct nk_context *, const char *, int, int *active)
nk_uint nk_hash
Definition: nuklear.h:404
NK_API int nk_str_len(struct nk_str *)
nk_command_type
Definition: nuklear.h:2819
NK_API nk_flags nk_edit_string(struct nk_context *, nk_flags, char *buffer, int *len, int max, nk_plugin_filter)
NK_API void nk_edit_unfocus(struct nk_context *)
unsigned int old
Definition: nuklear.h:3821
nk_size calls
Definition: nuklear.h:2543
Definition: nuklear.h:686
Definition: nuklear.h:1746
struct nk_vec2 pos
Definition: nuklear.h:3051
Definition: nuklear.h:2552
struct nk_style_item hover
Definition: nuklear.h:3491
Definition: nuklear.h:684
NK_API int nk_combo_item_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags alignment)
NK_API int nk_combo_begin_symbol_text(struct nk_context *, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:2046
#define NK_INPUT_MAX
Definition: nuklear.h:257
NK_API int nk_menu_begin_symbol_label(struct nk_context *, const char *, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:1894
NK_API void nk_buffer_free(struct nk_buffer *)
Definition: nuklear.h:2832
struct nk_style_item hover
Definition: nuklear.h:3592
NK_API struct nk_color nk_hsv_f(float h, float s, float v)
nk_hash name
Definition: nuklear.h:3846
struct nk_style_item cursor_active
Definition: nuklear.h:3405
struct nk_color color
Definition: nuklear.h:2922
struct nk_style_item normal
Definition: nuklear.h:3358
NK_API int nk_button_symbol(struct nk_context *, enum nk_symbol_type)
NK_API int nk_checkbox_label(struct nk_context *, const char *, int *active)
int use_pool
Definition: nuklear.h:4035
enum nk_symbol_type minimize_symbol
Definition: nuklear.h:3599
struct nk_vec2 scroll_delta
Definition: nuklear.h:3054
enum nk_panel_type type
Definition: nuklear.h:3808
NK_API int nk_window_is_closed(struct nk_context *, const char *)
struct nk_vec2 padding
Definition: nuklear.h:3310
Definition: nuklear.h:469
Definition: nuklear.h:685
NK_API int nk_group_begin(struct nk_context *, const char *title, nk_flags)
struct nk_rect header
Definition: nuklear.h:3815
float h
Definition: nuklear.h:3757
Definition: nuklear.h:2972
Definition: nuklear.h:2917
NK_API void nk_buffer_info(struct nk_memory_status *, struct nk_buffer *)
NK_API const char * nk_str_at_const(const struct nk_str *, int pos, nk_rune *unicode, int *len)
struct nk_color symbol_normal
Definition: nuklear.h:3545
struct nk_vec2 delta
Definition: nuklear.h:3053
Definition: nuklear.h:3953
#define NK_COLOR_STACK_SIZE
Definition: nuklear.h:3922
float row_padding
Definition: nuklear.h:3485
int down
Definition: nuklear.h:3045
struct nk_style_item normal
Definition: nuklear.h:3293
enum nk_panel_row_layout_type type
Definition: nuklear.h:3734
NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color)
Definition: nuklear.h:981
#define NK_BETWEEN(x, a, b)
Definition: nuklear.h:4057
NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx)
NK_API void nk_clear(struct nk_context *)
struct nk_color cursor_border_color
Definition: nuklear.h:3406
Definition: nuklear.h:2022
Definition: nuklear.h:674
float w
Definition: nuklear.h:457
struct nk_color border_color
Definition: nuklear.h:3493
NK_API void nk_menu_end(struct nk_context *)
#define NK_CONTAINER_OF(ptr, type, member)
Definition: nuklear.h:4098
struct nk_style_item hover
Definition: nuklear.h:3324
NK_API int nk_selectable_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int *value)
struct nk_style_button minimize_button
Definition: nuklear.h:3597
struct nk_style_item cursor_normal
Definition: nuklear.h:3429
NK_API nk_flags nk_chart_push(struct nk_context *, float)
NK_API unsigned nk_check_flags_label(struct nk_context *, const char *, unsigned int flags, unsigned int value)
float rounding
Definition: nuklear.h:3345
NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags)
NK_API float nk_propertyf(struct nk_context *, const char *name, float min, float val, float max, float step, float inc_per_pixel)
NK_API int nk_input_is_key_released(const struct nk_input *, enum nk_keys)
Definition: nuklear.h:495
struct nk_color cursor_hover
Definition: nuklear.h:3464
struct nk_style_item hover
Definition: nuklear.h:3398
Definition: nuklear.h:2864
Definition: nuklear.h:2949
enum nk_command_type type
Definition: nuklear.h:2843
float rounding
Definition: nuklear.h:3557
struct nk_style_button inc_button
Definition: nuklear.h:3443
struct nk_color text_active
Definition: nuklear.h:3471
NK_API struct nk_rect nk_widget_bounds(struct nk_context *)
struct nk_config_stack_vec2 vectors
Definition: nuklear.h:3956
float border
Definition: nuklear.h:3578
Definition: nuklear.h:473
Definition: nuklear.h:2825
short y
Definition: nuklear.h:2852
NK_API void nk_window_show_if(struct nk_context *, const char *name, enum nk_show_states, int cond)
NK_API int nk_tree_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
nk_color_format
Definition: nuklear.h:473
struct nk_command header
Definition: nuklear.h:2991
float combo_border
Definition: nuklear.h:3629
struct nk_color cursor_normal
Definition: nuklear.h:3463
struct nk_command header
Definition: nuklear.h:2983
nk_hash keys[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:3971
NK_API struct nk_color nk_hsv_iv(const int *hsv)
NK_API int nk_menu_begin_image(struct nk_context *, const char *, struct nk_image, struct nk_vec2 size)
struct nk_color popup_border_color
Definition: nuklear.h:3620
NK_API int nk_menu_begin_image_label(struct nk_context *, const char *, nk_flags align, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:3982
NK_API int nk_str_insert_at_char(struct nk_str *, int pos, const char *, int)
Definition: nuklear.h:1711
Definition: nuklear.h:2692
NK_API int nk_selectable_text(struct nk_context *, const char *, int, nk_flags align, int *value)
NK_UINT16 nk_ushort
Definition: nuklear.h:398
Definition: nuklear.h:2964
Definition: nuklear.h:1743
Definition: nuklear.h:3796
unsigned int old
Definition: nuklear.h:3840
nk_size size
Definition: nuklear.h:2580
enum nk_panel_type type
Definition: nuklear.h:3762
NK_API int nk_input_is_mouse_down(const struct nk_input *, enum nk_buttons)
NK_API nk_size nk_prog(struct nk_context *, nk_size cur, nk_size max, int modifyable)
NK_API int nk_filter_float(const struct nk_text_edit *, nk_rune unicode)
struct nk_vec2i begin
Definition: nuklear.h:2867
Definition: nuklear.h:3790
nk_handle callback_data
Definition: nuklear.h:2986
NK_API void nk_input_end(struct nk_context *)
NK_API int nk_button_pop_behavior(struct nk_context *)
float h
Definition: nuklear.h:457
struct nk_color selected_normal
Definition: nuklear.h:3474
NK_API void nk_layout_row(struct nk_context *, enum nk_layout_format, float height, int cols, const float *ratio)
NK_API void nk_layout_row_template_end(struct nk_context *)
Definition: nuklear.h:2043
Definition: nuklear.h:1721
struct nk_style_button dec_button
Definition: nuklear.h:3444
float rounding
Definition: nuklear.h:3636
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3392
NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a)
struct nk_style_edit edit
Definition: nuklear.h:3509
NK_API int nk_combo_string(struct nk_context *, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size)
struct nk_style_toggle option
Definition: nuklear.h:3661
struct nk_panel pan
Definition: nuklear.h:3978
Definition: nuklear.h:678
NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
struct nk_buffer_marker marker[NK_BUFFER_MAX]
Definition: nuklear.h:2564
NK_API int nk_combo_begin_image_text(struct nk_context *, const char *selected, int, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:2835
Definition: nuklear.h:2036
char string[1]
Definition: nuklear.h:2999
Definition: nuklear.h:2049
int heuristic(Location a, Location b)
Definition: findpath.cpp:58
nk_plugin_copy copy
Definition: nuklear.h:2695
Definition: nuklear.h:3259
struct nk_vec2 size offset
Definition: nuklear.h:462
struct nk_style_item normal
Definition: nuklear.h:3397
NK_API int nk_selectable_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int *value)
Definition: nuklear.h:666
struct nk_style_button node_minimize_button
Definition: nuklear.h:3573
Definition: nuklear.h:3731
nk_handle userdata
Definition: nuklear.h:3286
unsigned short line_thickness
Definition: nuklear.h:2936
NK_API int nk_check_text(struct nk_context *, const char *, int, int active)
short y
Definition: nuklear.h:2995
struct nk_text_edit text_edit
Definition: nuklear.h:4029
NK_API int nk_style_push_style_item(struct nk_context *, struct nk_style_item *, struct nk_style_item)
Definition: nuklear.h:2051
NK_API void nk_textedit_delete(struct nk_text_edit *, int where, int len)
int slot
Definition: nuklear.h:3716
NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed)
struct nk_style_item active
Definition: nuklear.h:3295
char name_string[NK_WINDOW_MAX_NAME]
Definition: nuklear.h:3847
Definition: nuklear.h:4005
typedef int(ENET_CALLBACK *ENetInterceptCallback)(struct _ENetHost *host
Definition: nuklear.h:2856
struct nk_page_element * prev
Definition: nuklear.h:3985
short x
Definition: nuklear.h:458
enum nk_anti_aliasing shape_AA
Definition: nuklear.h:984
Definition: nuklear.h:1710
struct nk_rect clip
Definition: nuklear.h:3009
struct nk_panel * layout
Definition: nuklear.h:3853
int length
Definition: nuklear.h:2998
NK_API void nk_style_set_font(struct nk_context *, const struct nk_user_font *)
struct nk_color left
Definition: nuklear.h:2894
Definition: nuklear.h:2873
struct nk_str string
Definition: nuklear.h:2727
nk_handle userdata
Definition: nuklear.h:3514
Definition: nuklear.h:466
Definition: nuklear.h:1885
#define const
Definition: zconf.h:196
short char_storage
Definition: nuklear.h:2702
short redo_char_point
Definition: nuklear.h:2711
int sel_start
Definition: nuklear.h:3824
struct nk_command header
Definition: nuklear.h:2865
short x
Definition: nuklear.h:2984
struct nk_clipboard clip
Definition: nuklear.h:4010
float border_cursor
Definition: nuklear.h:3437
NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color)
struct nk_vec2 content_padding
Definition: nuklear.h:3558
unsigned short line_thickness
Definition: nuklear.h:2876
enum nk_style_item_type type
Definition: nuklear.h:3255
NK_API void nk_label_colored(struct nk_context *, const char *, nk_flags align, struct nk_color)
struct nk_style_item active
Definition: nuklear.h:3593
Definition: nuklear.h:3831
Definition: nuklear.h:471
struct nk_color text_normal
Definition: nuklear.h:3303
Definition: nuklear.h:690
struct nk_color label_hover
Definition: nuklear.h:3541
Definition: nuklear.h:2045
NK_API int nk_check_label(struct nk_context *, const char *, int active)
struct nk_command header
Definition: nuklear.h:2942
NK_API void nk_window_set_bounds(struct nk_context *, struct nk_rect bounds)
nk_layout_format
Definition: nuklear.h:475
struct nk_color bar_filled
Definition: nuklear.h:3367
Definition: nuklear.h:2052
Definition: nuklear.h:3291
Definition: nuklear.h:452
Definition: nuklear.h:3003
short y
Definition: nuklear.h:456
NK_API void nk_end(struct nk_context *ctx)
NK_API int nk_menu_begin_symbol(struct nk_context *, const char *, enum nk_symbol_type, struct nk_vec2 size)
NK_API int nk_strfilter(const char *text, const char *regexp)
NK_API void nk_combobox_string(struct nk_context *, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size)
nk_text_width_f width
Definition: nuklear.h:2367
char buffer[NK_MAX_NUMBER_BUFFER]
Definition: nuklear.h:3833
Definition: nuklear.h:494
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3317
NK_API char * nk_str_get(struct nk_str *)
NK_UINT8 nk_byte
Definition: nuklear.h:396
#define NK_CHART_MAX_SLOT
Definition: nuklear.h:3687
struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]
Definition: nuklear.h:2706
unsigned short h
Definition: nuklear.h:2878
Definition: nuklear.h:2562
Definition: nuklear.h:460
Definition: nuklear.h:493
NK_API int nk_str_append_str_runes(struct nk_str *, const nk_rune *)
NK_API struct nk_color nk_rgba_fv(const float *rgba)
struct nk_config_stack_float floats
Definition: nuklear.h:3955
nk_uint x
Definition: nuklear.h:463
struct nk_style_button tab_maximize_button
Definition: nuklear.h:3570
#define NK_UNUSED(x)
Definition: nuklear.h:4053
int down
Definition: nuklear.h:3061
Definition: nuklear.h:3254
NK_INT16 nk_short
Definition: nuklear.h:397
short x
Definition: nuklear.h:2885
NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context *)
Definition: nuklear.h:1878
NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context *)
NK_API struct nk_rect nk_window_get_content_region(struct nk_context *)
NK_API int nk_select_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int value)
float grow_factor
Definition: nuklear.h:2572
struct nk_vec2 uv
Definition: nuklear.h:979
nk_uint * scroll_pointer
Definition: nuklear.h:1684
Definition: nuklear.h:452
Definition: nuklear.h:471
NK_API void nk_layout_space_begin(struct nk_context *, enum nk_layout_format, float height, int widget_count)
unsigned int seq
Definition: nuklear.h:4043
Definition: nuklear.h:454
int select_end
Definition: nuklear.h:3837
nk_text_edit_mode
Definition: nuklear.h:2719
struct nk_config_stack_color colors
Definition: nuklear.h:3958
struct nk_edit_state edit
Definition: nuklear.h:3859
struct nk_color label_active
Definition: nuklear.h:3542
NK_API void nk_style_from_table(struct nk_context *, const struct nk_color *)
int sel_end
Definition: nuklear.h:3825
#define NK_UINT8
Definition: nuklear.h:340
struct nk_input input
Definition: nuklear.h:4007
NK_API int nk_button_label(struct nk_context *, const char *title)
#define NK_MAX(a, b)
Definition: nuklear.h:316
const struct nk_user_font * font
Definition: nuklear.h:3651
float w
Definition: nuklear.h:3757
enum nk_button_behavior button_behavior
Definition: nuklear.h:4012
struct nk_context * ctx
unsigned short table_size
Definition: nuklear.h:3864
NK_API int nk_button_text(struct nk_context *, const char *title, int len)
#define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)
Definition: nuklear.h:4062
NK_API void nk_menubar_begin(struct nk_context *)
NK_API int nk_style_push_float(struct nk_context *, float *, float)
#define NK_PTR_TO_UINT(x)
Definition: nuklear.h:4083
#define NK_FONT_STACK_SIZE
Definition: nuklear.h:3902
NK_API int nk_combo_item_label(struct nk_context *, const char *, nk_flags alignment)
NK_API int nk_button_image_label(struct nk_context *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_button_image_text(struct nk_context *, struct nk_image img, const char *, int, nk_flags alignment)
Definition: nuklear.h:673
Definition: nuklear.h:2698
NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color)
NK_API int nk_str_insert_str_char(struct nk_str *, int pos, const char *)
struct nk_vec2i points[1]
Definition: nuklear.h:2969
Definition: nuklear.h:2019
struct nk_vec2 padding
Definition: nuklear.h:3378
NK_API int nk_menu_begin_label(struct nk_context *, const char *, nk_flags align, struct nk_vec2 size)
unsigned char grabbed
Definition: nuklear.h:3056
NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color)
unsigned char mode
Definition: nuklear.h:3827
NK_API int nk_style_pop_flags(struct nk_context *)
NK_API int nk_button_symbol_text_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API struct nk_color nk_rgb_hex(const char *rgb)
struct nk_style_item hover
Definition: nuklear.h:3535
nk_symbol_type
Definition: nuklear.h:489
NK_API struct nk_color nk_rgb_bv(const nk_byte *rgb)
NK_API int nk_str_insert_str_utf8(struct nk_str *, int pos, const char *)
struct nk_allocator pool
Definition: nuklear.h:2566
NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region)
struct nk_color text_background
Definition: nuklear.h:3306
short cy
Definition: nuklear.h:2943
Definition: nuklear.h:687
NK_API void nk_plot_function(struct nk_context *, enum nk_chart_type, void *userdata, float(*value_getter)(void *user, int index), int count, int offset)
struct nk_vec2 image_padding
Definition: nuklear.h:3282
NK_API nk_rune nk_str_rune_at(const struct nk_str *, int pos)
struct nk_scroll offset
Definition: nuklear.h:3758
NK_API int nk_style_pop_font(struct nk_context *)
struct nk_style_item hover
Definition: nuklear.h:3294
nk_command_clipping
Definition: nuklear.h:3002
tuple output
Definition: gtest_output_test.py:321
Definition: nuklear.h:3064
int columns
Definition: nuklear.h:3737
unsigned short r
Definition: nuklear.h:2935
int text_len
Definition: nuklear.h:3067
NK_INT32 nk_int
Definition: nuklear.h:399
NK_API int nk_tree_state_push(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states *state)
float border
Definition: nuklear.h:3480
NK_API void nk_input_unicode(struct nk_context *, nk_rune)
Definition: nuklear.h:698
NK_API void nk_textedit_redo(struct nk_text_edit *)
NK_API void nk_menu_close(struct nk_context *)
Definition: nuklear.h:472
NK_API struct nk_vec2 nk_rect_size(struct nk_rect)
Definition: nuklear.h:671
struct nk_style_item background
Definition: nuklear.h:3521
NK_API void nk_str_init(struct nk_str *, const struct nk_allocator *, nk_size size)
NK_API struct nk_image nk_image_id(int)
short y
Definition: nuklear.h:2885
struct nk_color color
Definition: nuklear.h:2938
Definition: nuklear.h:3727
NK_API int nk_combo_begin_image(struct nk_context *, struct nk_image img, struct nk_vec2 size)
Definition: nuklear.h:2821
#define nk_vec2_len_sqr(a)
Definition: nuklear.h:4067
struct nk_style_button inc_button
Definition: nuklear.h:3510
void(* draw_begin)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:3287
struct nk_style_item active
Definition: nuklear.h:3425
struct nk_command header
Definition: nuklear.h:2918
Definition: nuklear.h:2056
Definition: nuklear.h:3246
NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color)
NK_API void nk_combo_end(struct nk_context *)
Definition: nuklear.h:2834
NK_API int nk_propertyi(struct nk_context *, const char *name, int min, int val, int max, int step, float inc_per_pixel)
Definition: nuklear.h:3694
nk_size calls
Definition: nuklear.h:2578
NK_API void nk_input_char(struct nk_context *, char)
Definition: nuklear.h:2882
NK_API void nk_color_dv(double *rgba_out, struct nk_color)
struct nk_page_element win[1]
Definition: nuklear.h:3991
#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1)
Definition: nuklear.h:4060
NK_API struct nk_vec2 nk_vec2v(const float *xy)
NK_API int nk_tooltip_begin(struct nk_context *, float width)
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3318
NK_API struct nk_rect nk_recti(int x, int y, int w, int h)
NK_API struct nk_panel * nk_window_get_panel(struct nk_context *)
struct nk_vec2 menu_padding
Definition: nuklear.h:3646
struct nk_color label_normal
Definition: nuklear.h:3496
nk_size offset
Definition: nuklear.h:2559
nk_show_states
Definition: nuklear.h:470
struct nk_color color
Definition: nuklear.h:3260
struct nk_style_item pressed
Definition: nuklear.h:3325
NK_API int nk_style_pop_color(struct nk_context *)
NK_API struct nk_color nk_rgba_iv(const int *rgba)
unsigned char single_line
Definition: nuklear.h:3828
struct nk_color selected_hover
Definition: nuklear.h:3475
NK_API void nk_chart_end(struct nk_context *)
short x
Definition: nuklear.h:2927
struct nk_command_buffer * buffer
Definition: nuklear.h:3776
float a
Definition: nuklear.h:454
struct nk_color menu_border_color
Definition: nuklear.h:3623
NK_API int nk_menu_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
Definition: nuklear.h:465
Definition: nuklear.h:1745
Definition: nuklear.h:3723
NK_API int nk_combo_begin_symbol_label(struct nk_context *, const char *selected, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:472
#define NK_ALIGN_PTR_BACK(x, mask)
Definition: nuklear.h:4094
NK_API int nk_style_push_vec2(struct nk_context *, struct nk_vec2 *, struct nk_vec2)
nk_heading
Definition: nuklear.h:465
#define nk_vec2_muls(a, t)
Definition: nuklear.h:4068
nk_style_colors
Definition: nuklear.h:2017
NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context *)
NK_API int nk_menu_begin_text(struct nk_context *, const char *title, int title_len, nk_flags align, struct nk_vec2 size)
struct nk_color background
Definition: nuklear.h:2993
struct nk_vec2i end
Definition: nuklear.h:2868
nk_handle userdata
Definition: nuklear.h:3011
Definition: nuklear.h:491
NK_API struct nk_rect nk_rectiv(const int *xywh)
unsigned short h
Definition: nuklear.h:461
struct nk_color border_color
Definition: nuklear.h:3566
NK_API struct nk_vec2 nk_widget_size(struct nk_context *)
NK_API void nk_layout_row_push(struct nk_context *, float value)
nk_flags text_alignment
Definition: nuklear.h:3307